Setting up a Gentoo Server
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
- Prerequisites
- General-purpose user
- Remote login configuration
- Firewall
- Server identity
- Gentoo package profiles
- Portage/Make setup
- Locale
- Rebuild
- Reboot
- Conclusion
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.
Prerequisites
- Root access
- x86-64 architecture is assumed and recommended
- Time. Lots of it.
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
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.
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
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
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-#
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.
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
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
Reboot
Well, that’s easy enough.
reboot
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.