Ubuntu setup guide

Introduction

This guide covers the installation and customization of Ubuntu LTS (12.04 or 14.04).

The main differences between the configuration from this guide and the default Ubuntu configuration are:

Installation

Download ISO image

Images are available to download from releases.ubuntu.com. It is best to use an LTS (long-term support) version.

This guide covers the server installation, which can then be converted to a desktop installation. It might be faster/easier to use the desktop installation instead, the disadvantage being that it is be somewhat bloated. In any case, note that only the "server" and the "alternate" images support configurable partition encryption. This guide covers the installation of Ubuntu 12.04 LTS using the "server" image.

Burn the ISO image

The easiest way is to burn the image to CD/DVD. Alternatively, the image can be written to a USB key from a Ubuntu machine using Startup Disk Creator (package: usb-creator-gtk or usb-creator-kde).

Installation

The text-based installer uses only the keyboard (not the mouse). Use the "Enter" key to push buttons, the "Tab" key to navigate the GUI and the "Space" key to toggle checkboxes.

The installation steps for a setup with an encrypted root partition are shown in the following screenshots:

  1. Install
  2. Language
  3. Location
  4. Keyboard
  5. Keyboard
  6. Keyboard
  7. Hostname and network configuration
  8. User
  9. User
  10. Password
  11. Password
  12. Time zone
  13. Manual partitioning
  14. Create partition table
  15. Create partition table
  16. Create the boot partition
  17. Create the boot partition
  18. Create the boot partition: 2-4 GB is sufficient
  19. Create the boot partition: set as primary
  20. Create the boot partition: placed at the beginning of the disk, if possible
  21. Configure the boot partition
  22. Configure the boot partition
  23. Configure the boot partition
  24. Configure the boot partition: options for SSD durability
  25. Configure the boot partition
  26. Configure the boot partition
  27. Configure the boot partition
  28. Configure the boot partition
  29. Create the encrypted root partition
  30. Create the encrypted root partition
  31. Create the encrypted root partition: for SSD durability, use 80% of total disk size
  32. Create the encrypted root partition: either primary or logical works, since this is not a boot partition
  33. Create the encrypted root partition
  34. Create the encrypted root partition: encrypt the partition with dm-crypt (LVM could work too, but it reduces SSD lifetime)
  35. Create the encrypted root partition
  36. Create the encrypted root partition
  37. Create the encrypted root partition
  38. Create the encrypted root partition
  39. Create the encrypted root partition
  40. Create the encrypted root partition
  41. Create the encrypted root partition
  42. Create the encrypted root partition
  43. Create the encrypted root partition
  44. Configure the root partition
  45. Configure the root partition
  46. Configure the root partition
  47. Configure the root partition
  48. Configure the root partition: options for SSD durability
  49. Configure the root partition
  50. Configure the root partition
  51. Configure the root partition
  52. Configure the root partition
  53. Finalize partitioning
  54. Finalize partitioning
  55. No proxy
  56. Automatic updates
  57. No server software
  58. Install bootloader
  59. Reboot
  60. Enter the password for accessing the root partition
  61. Login
  62. It works

Initial configuration

Getting root (administrator) access

Run this command and enter the user password:

sudo su

Now we have a root console. It might be a good idea to set a root password to be able to login directly:

passwd

Install updates

Clean the apt cache (this needs to be done only once after installation):

rm -rf /var/lib/apt/lists

Then update:

apt-get update
apt-get dist-upgrade

Reboot:

reboot

Setup the console

The shell zsh is more user friendly than bash. Install it and set it as default shell for root and the user bob:

apt-get install zsh
chsh -s $(which zsh) root
chsh -s $(which zsh) bob

The zsh configuration file that you can find here offers some nice features, such as smarter command completion, colored prompt, git prompt, large command history and environment variables. Save it to /root/.zshrc and /home/bob/.zshrc:

cd
wget http://wiki.epfl.ch/git-epfl/documents/files/.zshrc
su bob
cd
wget http://wiki.epfl.ch/git-epfl/documents/files/.zshrc

The fonts used by Ubuntu in the terminal look ugly. It is possible to replace them with the more common VGA fonts:

dpkg-reconfigure console-setup
update-initramfs -u -k all
setupcon

Result: screenshot.

Midnight commander

Midnight commander or mc is a console-based file manager and editor:

apt-get install mc

Essential file manager (mc) shortcuts:

  • View file: F3
  • Edit file: F4
  • Toggle terminal: Ctrl+O
  • Select file: Ins
  • Copy file: F5
  • Move file: F6
  • Delete file: F8
  • Search: Alt+Shift+?
  • Exit: F10 or exit

Essential text editor (mcedit) shortcuts:

  • Save: F2
  • Toggle selection mode: F3
  • Copy selection to cursor: F5
  • Move selection to cursor: F6
  • Delete selection: F8
  • Exit: Esc Esc

The FbTerm console

The default linux terminal is very limited in terms of colors and font sizes available. Another option is installing fbterm:

apt-get install fbterm

To enter fbterm, simply run:

fbterm

The Liberation fonts look better in fbterm, and mc also looks better with the darkfar color scheme:

apt-get install fonts-liberation
sed 's/skin=default/skin=darkfar/' -i ~/.config/mc/ini
sed 's/editor_visible_tabs=1/editor_visible_tabs=0/' -i ~/.config/mc/ini
sed 's/editor_visible_spaces=1/editor_visible_spaces=0/' -i ~/.config/mc/ini
sed 's/font-names=mono/font-names=Liberation Sans/' -i ~/.fbtermrc
sed 's/font-size=12/font-size=13/' -i ~/.fbtermrc

Finally, to make the fbterm font color lighter, run once inside fbterm:

echo -en "\e]P7dedede"

Result: screenshot 1 and screenshot 2.

Networking

Basic firewall configuration

Create the executable script /etc/iptables-setup.sh:

touch /etc/iptables-setup.sh
chmod 700 /etc/iptables-setup.sh

Write the following contents into /etc/iptables-setup.sh:

#!/bin/bash

# Ignore pings sent to broadcast/multi-cast addresses.
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# Drop source routed packets
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
# Enable TCP SYN cookies
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
# Ignore ICMP redirect packets
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
# Do not send ICMP redirects
echo 0 >/proc/sys/net/ipv4/conf/all/send_redirects
# Enable source spoofing protection
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter

# Delete all the rules and chains from the filter, nat, mangle and raw tables:
iptables -t filter -F
iptables -t filter -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -t raw -F
iptables -t raw -X

# By default, drop all input traffic and allow output traffic:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Allow traffic originating from the loopback interface
iptables -A INPUT -i lo -j ACCEPT

# Allow traffic which is a reply to something we sent (allow web browsing etc):
iptables -A INPUT -m conntrack --ctstate related,established -j ACCEPT

Execute the script manually:

/etc/iptables-setup.sh

Check that the iptables rules correspond:

iptables -L -n -v

Add the script to be executed before each interface is activated by editing /etc/network/interfaces and adding the pre-up line for each interface:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
    pre-up /etc/iptables-setup.sh

Opening ports through the firewall

To allow some incoming traffic to your machine, edit /etc/iptables-setup.sh and add at the end extra INPUT rules like this:

# Examples for opening ports:

# Allow incoming traffic from everywhere to TCP port 80 (web server):
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# Allow incoming traffic on interface eth0 to TCP port 80 (web server):
iptables -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT

# Allow incoming traffic from the IP range 1.2.3.0/24 to TCP port 80 (web server):
iptables -A INPUT -s 1.2.3.0/24 -p tcp --dport 80 -j ACCEPT

# Allow incoming ping traffic (ICMP with type 8):
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT

Wireless

Install prerequisites:

apt-get install wpasupplicant

Let's say that you want to connect to an access point with name "Home" and password "complicated". First, you need to convert the password into a key:

wpa_passphrase 'Home' 'complicated'

The output looks like this:

network={
    ssid="Home"
    #psk="complicated"
    psk=df50a29570ab5c02ad2f482154f1a7113acc0d18169c07710eb351acb1076836
}

The key is printed after psk=, which is in our example df50a29570ab5c02ad2f482154f1a7113acc0d18169c07710eb351acb1076836.

Then we must add an entry for the wireless interface (which is usually named wlan0, it is possible to find out the name by running the command iwconfig) in /etc/network/interfaces:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
    pre-up /etc/iptables-setup.sh

auto wlan0
iface wlan0 inet dhcp
    pre-up /etc/iptables-setup.sh
    wpa-ssid Home
    wpa-psk df50a29570ab5c02ad2f482154f1a7113acc0d18169c07710eb351acb1076836

Finally, activate the interface manually with:

ifup wlan0

Disable IPv6

If you do not have an IPv6 connection from your ISP, it is safer to disable it. Edit /etc/default/grub and find the line:

GRUB_CMDLINE_LINUX_DEFAULT=""
Replace it with:
GRUB_CMDLINE_LINUX_DEFAULT="ipv6.disable=1"
Then run:
update-grub

Use custom DNS servers

Let's say that we want to use Google's nameserver 8.8.8.8 instead of the one offered by DHCP. We must add the dns-nameservers option for each interface in /etc/network/interfaces:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
    pre-up /etc/iptables-setup.sh
    dns-nameservers 8.8.8.8

auto wlan0
iface wlan0 inet dhcp
    pre-up /etc/iptables-setup.sh
    wpa-ssid Home
    wpa-psk df50a29570ab5c02ad2f482154f1a7113acc0d18169c07710eb351acb1076836
    dns-nameservers 8.8.8.8

It is also possible and even recommended to configure the DHCP client to accept less options when connecting. Edit /etc/dhcp/dhclient.conf and find the lines prepend domain-name-servers and request. Modify their content so that it looks like this:

prepend domain-name-servers 8.8.8.8;
request subnet-mask,
        broadcast-address,
        routers,
        interface-mtu,
        rfc3442-classless-static-routes;
Then run:
update-grub

Turn the computer into a NAT router

It is possible to use the computer as a NAT router, to allow other computers to connect to the network through it. For this it is necessary to have more than one network interface, for example two wired network cards or a wired network card and a wireless card (which most laptops have nowadays).

Enable routing

To enable routing until the next reboot, run:

echo 1 > /proc/sys/net/ipv4/ip_forward

To enable routing permanently, also add or uncomment in /etc/sysctl.conf:

net.ipv4.ip_forward=1

Setup NAT

To enable NAT, we need to edit the firewall settings from /etc/iptables-setup.sh. Let's assume that the network interface connected to the Internet (WAN) is eth0 and the network interface facing the local network (LAN) is wan0. The necessary firewall settings are:

# eth0 is WAN
# wlan0 is LAN

# Change the MTU of TCP SYN packets to 1400 for PPPoE or VPN
# 1500 - 20 reserved for encapsulation = 1480
# 1480 - 20 length of IP header without options = 1460 for transport
# 1460 - 60 maximum TCP header length = 1400
iptables -A OUTPUT  -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1400
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1400

# Allow all traffic coming from LAN to be routed
iptables -A FORWARD -i wlan0 -j ACCEPT

# Allow all traffic coming from WAN which is a reply to our traffic to be routed
iptables -A FORWARD -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

# Apply network address translation (NAT) to all traffic routed to WAN
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Apply the new rules:

/etc/iptables-setup.sh

Set a static IP address on the LAN interface

We need to configure the network interface facing the local network (LAN), which is wan0. It must have an IP address from one of the private IP ranges (10.0.0.0/8, 192.168.0.0/16 or 172.16.0.0/12). In this example we will use 192.168.100.1/24, which corresponds to the netmask 255.255.255.0. This is done by editing /etc/network/interfaces and assigning to wlan0 a static IP address:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
    pre-up /etc/iptables-setup.sh

auto wlan0
iface wlan0 inet static
    pre-up /etc/iptables-setup.sh
    address 192.168.100.1
    netmask 255.255.255.0
    # Use a smaller MTU for VPN or PPPoE
    mtu 1480

Activate the LAN interface:

ifup wlan0

Run a DHCP server for the LAN

We install a DHCP server:

apt-get install isc-dhcp-server

We edit the configuration in /etc/dhcp/dhcpd.conf, making sure we set options compatible to the settings for the LAN interface given above:

default-lease-time 600;
max-lease-time 7200;

option subnet-mask 255.255.255.0;
option broadcast-address 192.168.100.255;

# This is the IP address of our LAN interface
option routers 192.168.100.1;

option domain-name-servers 8.8.8.8;

# If we do not have a domain name, we just leave it like this
option domain-name "example.com";

# This is the pool of addresses which will be offered to the clients:
subnet 192.168.100.0 netmask 255.255.255.0 {
    range 192.168.100.100 192.168.100.200;
    # Use a smaller MTU for VPN or PPPoE
    option interface-mtu 1480;
}

We also need to add a firewall rule in /etc/iptables-setup.sh to allow incoming DHCP traffic from LAN, and also to allow ping (it is useful):

iptables -I INPUT -i wlan0 -p udp --dport 67:68 --sport 67:68 -j ACCEPT
iptables -I INPUT -i wlan0 -p icmp --icmp-type 8 -j ACCEPT

Finally, we need to start the DHCP server:

service isc-dhcp-server restart

Use the wireless interface as an Access Point

For a wired LAN interface, the steps above are sufficient. However, for a wireless LAN interface we need to install and configure a software wireless access point:

apt-get install hostapd
touch /etc/hostapd/hostapd.conf
chmod 600 /etc/hostapd/hostapd.conf

We use 802.11g protected with WPA2 Personal running on channel 7. The network name is "Home" and the password is "complicated". For security, it is important that wpa is set to 2 (WPA2) and that the pairwise algorithms use only CCMP (AES) and not TKIP (insecure). Also, the password must be much more complex than in this example!

We fill in the file /etc/hostapd/hostapd.conf:

interface=wlan0
driver=nl80211
country_code=US
ssid=Home
hw_mode=g
channel=7
wpa=2
wpa_passphrase=complicated
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
rsn_pairwise=CCMP
auth_algs=1
macaddr_acl=0

We must also edit the file /etc/default/hostapd:

DAEMON_CONF="/etc/hostapd/hostapd.conf"
RUN_DAEMON=yes
DAEMON_OPTS="-dd"

Finally, we start hostapd:

service hostapd restart
The clients should be able to connect.

Reduce latency over the LAN interface

This is especially useful for wireless. Add to /etc/iptables-setup.sh:

# Disable hardware checksumming, fragmentation etc.
# These increase latency on routers because they cause the packets to be processed in bursts.
for i in wlan0
do
    for f in rx tx sg tso ufo gso gro lro rxvlan txvlan ntuple rxhash
    do
        ethtool --offload $i $f off 1>/dev/null 2>/dev/null || true
    done
done

# Set low latency options
# Reduce the length of the wlan0 buffer from 1000 to 200 (lower might work well too, BSD uses only 50!)
ifconfig wlan0 txqueuelen 100

# Instead of FIFO buffers, use randomized fair queuing (i.e. behaves as if there are different buffers for different
# flows)
tc qdisc add dev wlan0 root sfq perturb 10 1>/dev/null 2>/dev/null || true
tc qdisc add dev eth0 root sfq perturb 10 1>/dev/null 2>/dev/null || true

Apply the new rules:

/etc/iptables-setup.sh

Port forwarding through the NAT router from WAN to LAN

This can be done by adding port forwarding commands to /etc/iptables-setup.sh, such as:

# Port forwarding example from WAN port 80 to port 80 of LAN machine at 192.168.100.105
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 192.168.100.105:80

# Port forwarding example from WAN port 80 to port 80 of LAN machine at 192.168.100.105,
# but only allowed from the source IP address in the range 1.2.3.0/24
iptables -t nat -A PREROUTING -s 1.2.3.0/24 -p tcp --dport 80 -j DNAT --to 192.168.100.105:80

Apply the new rules:

/etc/iptables-setup.sh

Installing a graphical interface

The XFCE desktop

For a full installation:

apt-get install xubuntu-desktop

For a minimalist installation:

apt-get install --no-install-recommends xubuntu-desktop xfce4-terminal

Result: screenshot 1 and screenshot 2.

Disable guest login $!

Run:

echo "allow-guest=false" >> /etc/lightdm/lightdm.conf
service lightdm restart

Disable the customized Ubuntu scrollbars (for full installs only)

Run:

apt-get remove overlay-scrollbar liboverlay-scrollbar-0.2-0 liboverlay-scrollbar3-0.2-0

CPU frequency selector system tray icon

Run:

apt-get install indicator-cpufreq
cp /usr/share/icons/ubuntu-mono-dark/status/22/indicator-cpufreq.svg /usr/share/icons/hicolor/22x22/status/
gtk-update-icon-cache -f /usr/share/icons/hicolor/

Remove PulseAudio and configure a proper ALSA mixer

Run (applies for full installs only):

apt-get remove pulseaudio
Save this file to ~/.asoundrc.

Nicer fonts

Set the default fonts to Liberations Sans, Liberation Mono from the appearance settings of the desktop (you might have to install the fonts-liberation package). Then, save this file as ~/.fonts.conf.

Applications

GCC and other development programs

Run:

apt-get install build-essentials make gcc g++ gdb git git-svn

Install a newer version of GCC

Run:

add-apt-repository ppa:ubuntu-toolchain-r/test
apt-get update
apt-get install gcc-4.9 g++-4.9
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.9
The new version is installed in parallel with the old one. It is possible to switch to the old version from the menu displayed by the command:
update-alternatives --config gcc

Install the Kate text editor

Run:

apt-get install --no-install-recommends kate

Update to the latest version of the KDE applications

Run:

apt-add-repository ppa:kubuntu-ppa/backports
apt-get update
apt-get dist-upgrade

Install Qt4 development files and tools

Run:

apt-get install --no-install-recommends libqt4-dev
The C++ IDE QtCreator should be installed from the website, so that the latest version is used: Qt downloads.

When using a newer gcc, certain compilation flags must be specified in every Qt project file (*.pro) to fix a debugging problem and to catch memory corruption bugs (reference 1, reference 2, reference 3, reference 4, reference 5):

QMAKE_CFLAGS += -std=gnu99 -fno-strict-overflow -fno-strict-aliasing -Wno-unused-local-typedefs -gdwarf-2
QMAKE_CXXFLAGS += -std=c++11 -fno-strict-overflow -fno-strict-aliasing -Wno-unused-local-typedefs -gdwarf-2
QMAKE_LFLAGS += -flto -fno-strict-overflow -fno-strict-aliasing

QMAKE_CFLAGS += -fstack-protector-all --param ssp-buffer-size=4
QMAKE_CXXFLAGS += -fstack-protector-all --param ssp-buffer-size=4
QMAKE_LFLAGS += -fstack-protector-all --param ssp-buffer-size=4

QMAKE_CFLAGS += -fPIE -pie -rdynamic
QMAKE_CXXFLAGS += -fPIE -pie -rdynamic
QMAKE_LFLAGS += -fPIE -pie -rdynamic

QMAKE_CFLAGS += -Wl,-z,relro,-z,now
QMAKE_CXXFLAGS += -Wl,-z,relro,-z,now
QMAKE_LFLAGS += -Wl,-z,relro,-z,now

Starting from gcc 4.8, a new compilation option is available for debugging memory allocation/corruption problems: AddressSanitizer. It is orders of magnitude faster than Valgrind. To use it, add the following compilation flags:

QMAKE_CFLAGS += -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic
QMAKE_CXXFLAGS += -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic
QMAKE_LFLAGS += -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic
To also check for memory leaks, run export ASAN_OPTIONS="detect_leaks=1" in the terminal before executing your program.

VirtualBox

For VirtualBox it is best to always use the latest image downloaded from www.virtualbox.org/wiki/Linux_Downloads. Then run:

dpkg -i virtualbox-.....deb

The installation might fail due to unresolved dependencies. This situation can be fixed with:

apt-get install -f

Accessing the virtual machine through the network

Configure the virtual machine to use NAT. Then, in the main VirtualBox window, go to File -> Preferences -> Network -> Host-only networks, add a new host-only network, click on Configure and make sure the DHCP server is enabled.

Turn off the virtual machine, then go to Settings -> Network -> Adapter 2 and select a host-only adapter attached to the host-only network we have just created. Save and reboot the virtual machine.

In the virtual machine, a new network interface appears. Configure it with DHCP, then find its IP address. The virtual machine is now accessible from the host using this IP address.