This guide begins with a fresh slice of CentOS 4.3 and configures the system as a web server that primarily serves Django applications.
Here is a broad overview of what will be covered in this guide:
“Part 2” of this guide is starting a New Django Project.
“Part 3” of this guide is starting a Shared Django Application.
NOTE: This guide is meant to be a copy-n-paste HowTo, so you should be able to do just that and get the expected results. When user-specific information is required I mark it with the
icon to clarify when copy-n-paste without modification is not recommended. When modifying files pay close attention if you copy-n-paste.
Sign in with root account.
Install vim-enhanced (because vi is terribly boring):
yum -y install vim-enhanced
Make a custom vim config file:
vi /etc/vimrc-custom
Paste these settings (comment any setting you do not want to use with " or simply delete the line):
if filereadable("/etc/vimrc")
source /etc/vimrc
endif
set nohls " do not highlight search matches
set nowrap " do not wrap long lines
set incsearch " show search matches while typing
set ignorecase " search is not case-sensitive
set background=dark " syntax highlighting softer w/ black bg
set autoindent " maintain indention for new lines
set smartindent " indent blocks intelligently
set shiftwidth=4 " use 4 spaces for 'smartindent'
set tabstop=4 " TABs displayed as 4 spaces
set expandtab " TAB key produces spaces
set showmatch " indicate completed ( ) and { } and [ ]
set matchtime=10 " showmatch for 1.0 second
" 'x' key just deletes text instead of cutting it.
noremap x "_x
Now symlink the vim custom config to the /etc/skel/ directory:
ln -s /etc/vimrc-custom /etc/skel/.vimrc
Edit the skeleton .bashrc file:
vi /etc/skel/.bashrc
Append the file with a couple aliases:
# Common aliases alias l='ls -l' alias vi='vim'
Use of the root account should be limited for obvious reasons. If those reasons are not obvious to you, then I suggest you check out the first link in my sources.
After you build your CentOS 4.3 slice, start a session with your favorite SSH client (e.g. PuTTY), and sign in with root.
First change the automatically generated password:
passwd
Next you will need sudo in order to access commands reserved for root from your non-root account that you will create shortly:
yum -y install sudo
To edit the config file for sudo it is best to use the visudo command:
visudo
Uncomment this line:
%wheel ALL=(ALL) ALL
Next you must create a new user who can use sudo. We will call this user admin:
useradd -Gwheel -cAdministrator admin
The -Gwheel part adds the administrator to the group wheel, and -cAdministrator is simply a descriptor (optional).
Don’t forget to set a password for admin:
passwd admin
NOTE: The following revision to the central /etc/profile configuration has only been tested for CentOS 5, please append any prior versions known to be successful If you make this revision, you do not need to make the ~/.bash_profile revision to PATH as detailed in the next step.
To avoid typing long path names when running sudo commands, modify /etc/profile to add them for the wheel superuser group
vi /etc/profile
Replace the line with ‘if [ “$EUID” = “0” ]; then’ to match the following four lines:
# when user is a member of "wheel" superuser group or effective user id is root # add the superuser paths id -Gn | grep -q -w wheel if [ $? = 0 -o "$EUID" = "0" ]; then
NOTE: The following is more helpful if you also create aliases for specific root commands.
To avoid typing long path names when running root commands, modify the admin user’s PATH:
vi /home/admin/.bash_profile
Change the line with PATH=... to match this:
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:$HOME/bin
(Optional) To actually disable the root account:
passwd -l root
If you disable root this way, then you won’t even be able to switch to root after logging in with a different user because this command makes the password for root invalid.
Close SSH session:
exit
NOTE: From now on you should never have to log in as or switch to root – using sudo allows you to execute any commands that require root access.
Start a new SSH session, and sign in with admin.
To ensure that only certain users can access the server via SSH let’s create a group called sshers:
sudo groupadd sshers
NOTE: sudo will prompt you for the admin account password the first time you use it, but it will not ask for your password again unless you do not use the sudo command for at least 5 minutes.
Add admin to the group sshers:
sudo usermod -a -Gsshers admin
Edit the SSH config file:
sudo vi /etc/ssh/sshd_config
Find and modify the following settings:
#Protocol 2,1 Protocol 2 #PermitRootLogin yes PermitRootLogin no #MaxAuthTries 6 MaxAuthTries 1 # optional - limit 2 login attempts per session GSSAPIAuthentication no # uncomment this line #GSSAPIAuthentication yes # comment this line #AllowTcpForwarding yes AllowTcpForwarding no X11Forwarding no # uncomment this line #X11Forwarding yes # comment this line ClientAliveInterval 300 # Send keep alive message every 5 minutes to prevent idle session disconnects. ClientAliveCountMax 3 # Kill client after 15 minutes if there is no response to keep alive messages. #UseDNS yes UseDNS no # optional - help boost speed for SSH sessions # add this line: AllowGroups sshers
Restart the SSH service so that the changes will take effect:
sudo service sshd restart
If you prefer to use RSA public key authentication there are plenty of guides available on the web. For Windows users with PuTTY (like me) there are instructions for creating a key pair in the PuTTY documentation: Chapter 8. Save the private key to your local machine, and copy the public key from the Public key for pasting box in PuTTY Key Generator.
Create an authorized_keys file:
mkdir ~/.ssh vi ~/.ssh/authorized_keys
Paste your public key to the authorized_keys file (right-click in PuTTY pastes). Make sure the key is on a single line. It starts with ssh-rsa and ends with your description; something like this:
ssh-rsa AA1yc2EAAAABJQAA7is0Ch2JEJLctyYQyjAc96R0CnXWYBkO9T3V4rawholelottarandomcharactersi+MEAAB3NzaCtGiDHist+6f6D+GIcUNnhTKBa4EduO0EvfiiJas9zlMq5bnQ9ZJHrb8Wabunchmorerandomcharacters5fETIEy+MUm7BA5E7oRgUdQ== Joe's Laptop
Remove group-writable and world-writable permissions from ~/.ssh/authorized_keys:
chmod go-w ~/.ssh/authorized_keys ~/.ssh/
After your verify the keys work, then you can disable password authentication:
sudo vi /etc/ssh/sshd_config
Find and modify the following settings:
PasswordAuthentication no UsePAM no # uncomment this line #UsePAM yes # comment this line
Don’t forget to restart the SSH service so that the changes will take effect:
sudo service sshd restart
Now your slice will immediately end a session that is not initiated with key authorization. Try to log in as admin without your key and the session should terminate without prompting for your password.
If you encrypt your private key with a password (as you should) but you don’t want to type that password each time you open a new PuTTY session, then check out Pageant.
Set your TCP wrappers to deny all connections:
sudo vi /etc/hosts.deny
Append this line:
ALL: ALL
Explicitly allow any type of local connection as well as all remote SSH connections:
sudo vi /etc/hosts.allow
Append these lines:
ALL: 127.0.0.1 sshd: <your-local-ip> sshd: <your-other-ip>
To block brute-force attacks on your SSH daemon you should allow only your home/office machine’s IP address(es).
Install iptables:
sudo yum -y install iptables
Edit iptables config file:
sudo vi /etc/sysconfig/iptables
Paste these settings:
# By default drop all incoming and forwarded traffic # Allow all outgoing traffic *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] # Allow returning packets -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow incoming traffic on ports 80 and 443 for web server -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Allow local traffic -A INPUT -i lo -j ACCEPT # Allow ping -A INPUT -p icmp --icmp-type ping -j ACCEPT # Allow incoming SSH -A INPUT -p tcp --dport 22 -j ACCEPT COMMIT
Change permissions on the iptables config file so only root can read it:
sudo chmod go-r /etc/sysconfig/iptables
Restart iptables service:
sudo service iptables restart
NOTE: For a details about the settings above, see the first link in my sources.
Disable network shares:
sudo chkconfig netfs off
Edit the hosts file:
sudo vi /etc/hosts
Add your website’s domain name:
127.0.0.1 example.com example
(Optional) Sometimes it’s helpful to query DNS servers. The bind-utils package contains some useful commands (dig, host, dnsquery and nslookup):
sudo yum -y install bind-utils
It is unlikely that your server will require IPv6, so let’s instruct the system to disable IPv6 when it boots.
Edit the modprobe config file:
sudo vi /etc/modprobe.conf.dist
Append this line:
alias net-pf-10 off
NOTE: Changes will not take effect until the system reboots, which we will do at the end of the next section.
Because all slices run on 64-bit virtual machines you should configure yum to ignore other packages. Also, Xen provides the kernel, so there is no need for yum to download or install new kernels.
Edit the yum config file:
sudo vi /etc/yum.conf
Append this line:
exclude=*.i386 *.i586 *.i686 kernel*
(Optional) A very useful feature of Django is sending e-mail, so let’s install postfix, a great MTA:
sudo yum -y install postfix
Next you should execute a full update. This will upgrade CentOS, the linux kernel, and all installed packages to their latest versions:
sudo yum -y update
Although it is rarely necessary to reboot a linux machine, we have made some changes to network settings and updated a lot of packages, so now is probably a good time to reboot:
sudo reboot
NOTE: Your SSH session will terminate while the slice reboots, but you will be able to reconnect very soon (usually less than 1 minute).
The following packages are required for Django:
Installing some of the required packages is very easy:
sudo yum -y install httpd mod_python postgresql-server subversion
I was not able to find two critical packages (psycopg and python imaging library) with the default repositories for yum, but luckily I found a repo maintained by a CentOS developer, Karanbir Singh (also here). You can add his repo file with this command:
sudo wget -P /etc/yum.repos.d/ http://centos.karan.org/kbsingh-CentOS-Extras.repo
Then it is possible to install psycopg and PIL with yum:
sudo yum -y install python-psycopg python-imaging
Finally, we will clean up downloaded files:
sudo yum clean all
Start the PostgreSQL service (initializes database also):
sudo service postgresql start
Set PostgreSQL to start automatically on boot:
sudo chkconfig postgresql on
Set password for user postgres:
sudo passwd postgres
Switch to postgres user:
su - postgres
Connect to the template1 database with PostgreSQL user postgres:
psql -d template1 -U postgres
Yes, the default PostgreSQL user is postgres, and the linux user postgres is different.
From the SQL command line, change the PostgreSQL user postgres‘s password:
ALTER USER postgres WITH PASSWORD '<new_pwd>';
Quit the SQL command line:
\q
Setting the password – which can differ from the password for the linux user postgres – will allow you to connect to the PostgreSQL command line as the PostgreSQL user postgres (if necessary) after changing the authentication settings in the next step.
Modify pg_hba.conf to require password authentication for local connections:
vi /var/lib/pgsql/data/pg_hba.conf
Comment or remove any existing lines at the end of the file, then append this:
local all all password
Close session as postgres and return to admin session:
exit
Restart the PostgreSQL server:
sudo service postgresql restart
With Subversion it is very easy to install the latest (trunk) Django source:
sudo svn co http://code.djangoproject.com/svn/django/trunk/ /usr/lib/python2.3/site-packages/django_trunk
The only other requirement is to create a couple symlinks:
sudo ln -s /usr/lib/python2.3/site-packages/django_trunk/django/ /usr/lib/python2.3/site-packages/django sudo ln -s /usr/lib/python2.3/site-packages/django/bin/django-admin.py /usr/bin/django-admin.py
Maybe I’m just very lazy, but I get tired of typing sudo <command> all the time. Luckily, we have aliases to help us avoid the tedium of that 4-character command, sudo.
My example focuses on the root commands used frequently in this guide, but I’m sure there are many others you may want to add to your own list.
(When logged in as admin) modify your .bashrc file:
vi /home/admin/.bashrc
Append the following lines:
# User command aliases alias useradd='sudo useradd' alias usermod='sudo usermod' alias userdel='sudo userdel' # Other aliases alias apachectl='sudo apachectl' alias chkconfig='sudo chkconfig' alias gpasswd='sudo gpasswd' alias service='sudo service' alias reboot='sudo reboot' alias yum='sudo yum' # Django update - to update the trunk in the future simply execute 'djupdate' alias djupdate='sudo svn co http://code.djangoproject.com/svn/django/trunk/ /usr/lib/python2.3/site-packages/django_trunk/'
These aliases will begin working at your next login, so close your current session and start a new one to test them.
You should now be able to simply execute, for example, yum update and the alias will actually execute sudo yum update.
ALL of the information in the guide was pulled from other guides. My only contribution is modifying, trimming, and organizing it to apply to my specific environment. I hope this is useful to someone else. If not, then at least it will be a good reference for me.
Implementing network security on CentOS/RHEL servers
First steps with your new CentOS slice
Prevent yum from installing non-x86 64-bit apps
The always-helpful guys in SliceHost's Campfire chat (now most of them can be found on irc.freenode.net in #slicehost)
...to everyone who helped make this possible!
– djangojoe