I run several web servers, mostly oriented toward serving Django applications, and have selected Gentoo as my Linux distribution of choice for secure, robust deployment. I’ve documented most of the boiler-plate setup so that I can rapidly launch a server, while tailoring it to specific needs (an area where Gentoo really shines). This is the first of 3 documents that will show boiler-plate setup, Django virtual hosting setup, and database setup respectively.

Contents

Introduction

Gentoo Linux is a fine operating system that allows the administrator to tailor software to meet the specific hardware and utility demands he is faced with. Setting up Gentoo, however, can be a daunting task at first when faced with Gentoo-specific commands, and compiling software from source (think MacPorts) rather than installing from prebuilt binaries. This guide takes you from a fresh install, likely on a virtual host—I use Linode—to a point where you can start thinking about your specific needs. This is the boiler plate.

Contents

Prerequisites

  • Root access
  • x86-64 architecture is assumed and recommended
  • Time. Lots of it.

Contents

General-purpose user

The first thing you’ll likely need is a user that has almost, but not full-blown, root ability. Create a user, in this case: fred.

useradd -m fred
passwd fred

Now edit fred’s permissions to have easy access to “sudo” (root) commands using the visudo tool.

visudo

Scroll down and uncomment the line %wheel ALL=(ALL) NOPASSWD: ALL and save the file. This gives any user in the ‘wheel’ group access to sudo commands without needing a password. Add fred to the wheel group and we’re rockin.

usermod -aG wheel fred

Contents

Remote login configuration

Since fred is basically a root user without the official title, we want that account to be super secure. Some people like to make a very hard password that no one, including themselves, can guess or remember. Personally, I like to forget the password notion all together, and set up SSH keys so that only the machines I specify can log in as fred. This is even more secure than a password, and makes my life easier by not having to type a long password every time I need to log in.

su - fred
cd .ssh
ssh-keygen -t rsa -C "fred@newserver"
echo "YOUR-LOCAL-MACHINES-SSH-PUB-KEY" >> authorized_keys
chmod 600 authorized_keys
exit

Perfect, now edit the SSH configuration file so that only fred can log in to this server.

vi /etc/ssh/sshd_config

Find and uncomment/change these 2 lines:

PermitRootLogin no
.
.
.
UsePAM no

And add this line to the bottom of the file:

AllowUsers fred

Save and exit.

Contents

Firewall

A firewall is a must have. It keeps the garbage out of your house, and informs you when someone is trying to break in. Gentoo, like other Linux distributions, uses iptables for this task. Since we are in the 21st century, we will have to create two iptable configurations: one for IPv4, and one for IPv6.

Create and edit a file called iptables.up.config:

vi /etc/iptables.up.config

This configuration is suited to the most basic needs (logging in and accepting HTTP requests). Over time, this may be modified as your needs evolve.

*filter

# Allow all loopback (lo0) traffic and drop all traffic to 127/8 that
# doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

# Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow all outbound traffic
-A OUTPUT -j ACCEPT

# Allow HTTP and HTTPS connections from anywhere
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allow SSH connections
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# Log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound (default deny)
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

Save and exit. Now create a similar file suited for IPv6.

vi /etc/ip6tables.up.config

And add your configuration:

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

# Allow all loopback (lo0) traffic
-A INPUT -i lo -j ACCEPT

# Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow all outbound traffic
-A OUTPUT -j ACCEPT

# Allow HTTP and HTTPS connections from anywhere
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allow SSH connections
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Allow icmp traffic
-A INPUT -p icmpv6 -j ACCEPT

# Log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "ip6tables denied: " --log-level 7

# Reject all other inbound (default deny)
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

Load the iptables records, save them, and tell Gentoo to start iptables automatically on boot.

iptables-restore < /etc/iptables.up.config
ip6tables-restore < /etc/ip6tables.up.config
/etc/init.d/iptables save
/etc/init.d/ip6tables save
rc-update add iptables boot
rc-update add ip6tables boot

At this point you may want to restart SSH and test that you can access fred’s account from another terminal.

/etc/init.d/sshd restart

Contents

Server identity

Establish a host name and, if you wish, a personal name for the server. First edit /etc/hosts

vi /etc/hosts

And replace its contents with your server’s information formatted like this:

IP-ADDRESS  FULLY-QUALIFIED-DOMAIN-NAME  DOMAIN

Save, exit, and run the Gentoo hostname tool:

hostname FULLY-QUALIFIED-DOMAIN-NAME

Contents

Gentoo package profiles

Gentoo’s packaging software, Portage, offers a solution-oriented set of “profiles” that give you a few extras when installing software. There is a default option with a few sub-options for those who don’t care. I recommend Gentoo’s hardened profile, since it has been carefully tailored for extra security.

First you will need to sync your portage tree:

emerge --sync

Then select a profile:

eselect profile list
eselect profile set DESIRED-PROFILE-#

Contents

Portage/Make setup

Now it’s time to refresh our package listings and install axel (a program that will help speed up downloads in the future). This will take several minutes. Of note here is the etc-update command. Explaining it’s usage is out of the scope of this document, but it basically is a config-file updater that detects changes programs want to make to existing configurations, and lets you review the changes and alter them if desired, or even refuse them altogether. It is important that you understand and pay attention to what this program tells you, because some software may want to overwrite changes you’ve just made! If you are not already familiar with etc-update, I implore you to read the documentation first before proceeding.

emerge --sync
etc-update
emerge axel -avq

And now the fun begins. Edit your make.conf file to suit your needs.

vi /etc/make.conf

Here is mine. I work with Python and PostgreSQL almost all of the time, and I enjoy a few optimizations to the compilation settings. This is a barebones, lean and mean make.conf, which is how I like to keep things. There are package-specific flags you can set outside of make.conf when the needs arise. For a more detailed explanation of these settings and what they do, read the make.conf man pages.

CFLAGS="-O2 -pipe -march=native -mno-tls-direct-seg-refs"
CXXFLAGS="${CFLAGS}"
CHOST="x86_64-pc-linux-gnu"
MAKEOPTS="-j3"
FEATURES="sandbox"
GENTOO_MIRRORS="http://mirror.mcs.anl.gov/pub/gentoo/ ftp://mirror.mcs.anl.gov/pub/gentoo/ http://www.gtlib.gatech.edu/pub/gentoo ftp://ftp.gtlib.gatech.edu/pub/gentoo"
SYNC="rsync://rsync.us.gentoo.org/gentoo-portage"
FETCHCOMMAND="/usr/bin/axel -a -o \${DISTDIR}/\${FILE} \${URI}"
RESUMECOMMAND="${FETCHCOMMAND}"

USE="mmx sse sse2"
USE="${USE} -alsa -cups -gnome -gtk -gtk2 -java -kde -oss -qt -sdl -X"

# Server-specific USE flags
USE="${USE} ipv6 python postgres -mysql -sqlite"

Save your make.conf and exit.

Contents

Locale

I cannot stress enough how important it is to set your system’s locale early and correctly. Whether you realize it or not, many packages depend dearly on these settings and when you discover that you were wrong, it may be too late. The de facto encoding standard is UTF-8, and I speak American English. Unless I have specific needs, my server should reflect this.

vi /etc/locale.gen

Uncomment this line:

en_US.UTF-8 UTF-8

Set the environment variable.

vi /etc/env.d/02locale

This file may or may not exist already. Regardless, it’s contents should be this one line:

LANG="en_US.UTF-8"

Now you need to set a proper timezone for the server. Remove the existing timezone data file (if it exists)

rm /etc/localtime

Find a new one, and symlink it:

ls /usr/share/zoneinfo
ln -s /usr/share/zoneinfo/America/New_York /etc/localtime

Specify the timezone in /etc/timezone

vi /etc/timezone
America/New_York

And make sure everything checks out:

date

Refresh your environment.

env-update && source /etc/profile

Contents

Rebuild

Now that our core settings are in place, it’s time to fetch the latest versions of Portage and GCC.

emerge portage
etc-update
emerge binutils gcc

Now at this point you likely have two or more versions of GCC installed. Get a list, and switch to the one you prefer. I do not use the variants like hardenednopie, hardenednossp, etc. If you don’t know what these are, you should not use them either. Currently, I’m using x86_64-pc-linux-gnu-4.5.3.

gcc-config -l
gcc-config YOUR-DESIRED-GCC #
source /etc/profile

Before we start the rebuild, I add one last USE flag for Python that I know iPython (my favorite Python interpreter) needs. You should do the same for any packages you know of that have specific USE flag needs.

echo "dev-lang/python sqlite" >> /etc/portage/package.use

And rebuild the system. Depending on your processor, this could take 5 hours or more.

emerge -e world

Welcome back. Time to tidy up our brand new server.

etc-update
grpck
grpconv
glsa-check -p affected

Most likely etc-update will want to change every configuration file on your system. Again, pay close attention as a few may have been edited by you, and you don’t want etc-update reverting your changes back to defaults.

If Python was upgraded, you’ll want to review the Python versions you have on your system and select the one you prefer.

eselect python list
eselect python set DESIRED-PYTHON-VERSION
python-updater

Clean out old programs and dependencies that are no longer needed.

emerge --depclean
revdep-rebuild

And install a few helper programs that you’ll likely want. (this part is optional, and some may already be installed depending on your Gentoo image)

emerge app-admin/logrotate -avq
emerge esearch -avq
eupdatedb
esearch sys-apps/less
emerge sys-apps/less -avq  #if needed
hash -r && source /etc/profile

Contents

Reboot

Well, that’s easy enough.

reboot

Contents

Conclusion

Pending any complications, you now have a fresh Gentoo server ready to be shaped into whatever you need it to be. For additional pointers, visit the Gentoo docs, or comment and/or email me if I have failed to make anything clear.