@reC suggested I put together a guide for setting up Gentoo Linux with a configuration suitable for use with Purism hardware. As I plan to write one for putting gentoo on the L5-E when it ships, I figure writing one for x86_64 should save some time later. As the Arch install guide by @dc3p is excellent, I’m largely following their layout.
Configuration:
- Gentoo Linux 17.1, desktop/plasma non-systemd
- Grub bootloader
- BIOS mode
- BTRFS compressed root
- fat32 /boot
- ZRam swap
- Jack audio with pulseaudio bridge
All the usual warning apply. If you have important data, back it up and test the backup before you start. If you can’t afford to have the laptop offline, don’t start. Gentoo is impressively stable, but it does require some care, the willingness to actually read error messages, and on low-end and mobile hardware, time. Expect to set the install up and let it run overnight, then spend a bit more time finishing up.
If you want to experiment with Gentoo, without risking leaving your computer unbootable, a chroot, VM, or prefix install is a good idea.
Things to know about Gentoo
- Rolling Source-based release
- All flavors (kde, gnome, et cetera) share the same repositories, and use different profiles for setting the default software.
- If you get stuck, the wiki is a good place to start. The #gentoo channel on freenode IRC is also reasonably friendly.
- Gentoo doesn’t have a conventional installer, like other distros. Instead, it requires any live system capable of using
chroot
for the initial setup.
Pre-Install
Before we can start the actual install, some basic setup is required. Now is also a good time to figure out things like what filesystem you want, what you want encrypted, and so on.
For use with a VM, you can use losetup to get yourself a loop block device. For a chroot install, you can skip this step and go to the install section.
General notes on partition layout and live system setup
- If you are running BTRFS as your main partition, you can install gentoo into a new subvolume, using the existing install as the live system.
- You cannot generally resize a partition while it is in use, so if you aren’t using a filesystem that supports subvolumes, you’ll need to at least use a portable live system if you need to shrink a partition to make space for Gentoo.
- If you want a portable install, putting Gentoo itself on an external USB stick works quite well, and it can then be used for installing other systems.
- If you’re bootstrapping without an existing system, I find the Linux Mint Debian liveCD works quite well for having a usable environment from which to install.
1. Partitioning the disk
I’m assuming /dev/sda
is the hard drive, and it’s only used for Gentoo. Adjust accordingly.
- GParted works well for disk partitioning
- Leave a 32 mb free at the start of the drive so we can be sure grub has enough space
- Create a partition for boot. Each kernel takes 15 MB or so. I usually devote 128MB to /boot. Format it to fat16. This gives you the best chance of rescue booting the system in the event of a hardware failure (and you move the drive to another computer).
- make sure to flag it bootable
- Create a partition for root out of the remaining space, format it BTRFS.
- If you want encryption, see the arch how-to for setting up luks and lvm.
2. Mount the new root partition
mkdir /tmp/mnt
mount /dev/sda2 /tmp/mnt -o subvol=/,noatime,compress=zlib:9,ssd
Obviously, if you’re using spinning rust, omit the ssd
option.
3. Setup the subvolumes
cd /tmp/mnt
btrfs subvolume create home
btrfs subvolume create root
btrfs subvolume create local
You may want etc
in its own subvolume, if you edit lots of config files yourself. You may want opt
as well, if you use proprietary software.
4. Remount the root partition with the correct subvolume
cd /tmp
umount mnt
mount -o subvol=root,noatime,compress=zlib:9,ssd /dev/sda2 /tmp/mnt
cd /tmp/mnt
mkdir -p home usr/local
mount /dev/sda2 home -o subvol=/home,noatime,compress=zlib:9,ssd
mount /dev/sda2 usr/local -o subvol=/local,noatime,compress=zlib:9,ssd
mount /dev/sda1 /boot
If you want better and faster compression, zstd
works better than zlib
, but requires a relatively recent kernel.
Install
1. Download the stage3 tarball.
- This can be done in advance, but I like to get a copy of it sitting in the new root.
- You can get stage3 from here.
- The standard version is at the top, if you want systemd, or some other preset profile, grab it from the list at the bottom. You can download it through your browser, or just right-click and copy-link-location
wget "link-from-above"
tar -xaf stage3-*
2. Mount everything needed in the chroot
mount --bind /dev dev
mount --bind /proc proc
mount --bind /sys sys
mount --bind /dev/pts dev/pts
cp /etc/resolv.conf etc
3. Chroot
chroot .
. /etc/profile
4. Get the latest repository snapshot
emerge-webrsync
5. Install minimal distcc
This lets you network computers together to speed up the install process. Skip if you only have one computer, or don’t want to install distcc on your other computer(s). Ideally, you want gigabit ethernet between the computers involved, but 100mb does ok.
USE="-gtk -ipv6 -zeroconf" emerge -av sys-devel/distcc
It will tell you what packages will be installed and prompt for confirmation.
On the helping computers, install the distcc server package (might be called distccd), then start distccd
user@helping-computer $ distccd --allow $specific_ip_or_safe_subnet --jobs $number_of_cpu_cores --log-stderr --no-detach
If you aren’t on a trusted network, you can use ssh port forwarding, but that is outside the scope of this guide.
Add each server to the list of distcc
servers
echo $ip_address_of_helping_computer/$number_of_jobs >> /etc/distcc/hosts
Once done, you can run distcc -j
to calculate how many distcc jobs to use
6. Customize make.conf
nano /etc/portage/make.conf
Add or change the following lines, you can skip the comments
$lowercase_variables should get customized to your set up.
To find your $arch value, run
gcc -march=native -Q --help=target | grep march
# Enable distcc and downloading multiple packages at once
FEATURES="distcc parallel-fetch"
# Enable parallel builds by default
MAKEOPTS="-l $number_of_cpus -j $number_of_distcc_jobs"
# Build for a specific CPU, leave it out if you want a portable install
COMMON_FLAGS="-O2 -pipe -march=$arch"
# If you want only free software, add the following
ACCEPT_LICENSE="-* @FREE"
# A slightly less restrictive setting, which allows open source, free to use, including non FSF approved licenses.
ACCEPT_LICENSE="* -@EULA"
VIDEO_CARDS="intel"
# At the next line if you want 32bit multiarch support
ABI_X86="64 32"
# Global use flags for when you want something always or never used
USE="-systemd -bindist jack -gnome openssl wayland elogind -consolekit"
7. Setup locale
eselect locale list
Pick a number from the list, which matches your preferred language (the utf8 version). You can pipe the output to grep if you know what you want
eselect locale list | grep en_US
Then set it.
eselect locale set 256
8. Setup timezone
emerge -av app-eselect/eselect-timezone
eselect timezone list | grep America/Los_Angeles
eselect timezone set 147
9. Install basic tools
emerge -avj gentoolkit eix genkernel btrfs-progs rsyslog unp lzop
eix-update
10. Get the kernel sources
If you want maximum efficiency, you need to set march=native
for the kernel build. This requires a set of patches still considered experimental, but which are reasonably stable, at least on x86_64.
echo sys-kernel/gentoo-sources experimental >> /etc/portage/package.use/gentoo-sources
Then it’s time to pick your kernel version,
eix gentoo-sources
will list the available version. The green ones are stable. If you want the latest features, grab the latest yellow one, it’s usually fine, and if it isn’t, changing later isn’t too hard. Note that you’ll need to run dispatch-conf
again if you want to run a version not marked stable.
emerge -av --autounmask gentoo-sources:5.4.7
Will grab the latest version (at the moment). Note that this is a slotted package, which means you can install multiple versions in parallel.
If it’s the first one installed, it will get automatically selected, but it’s good to manually check
eselect kernel list
You can pick whichever version you want as active. Once that’s done, get the .config
from the PureOS kernel, and copy it to /usr/src/linux
(in the chroot). apt-get source linux-kernel
from within PureOS should get the .config
, or you can get the source package manually through a web browser and unpack it. If you’re running PureOS, you may also be able to get it from /proc/config.gz
, but I don’t know if that is enabled or not.
11. Apply the configuration changes
We changed some global use flags back in step 6, so we want to rebuild the affected packages before we go asking for lots of installs.
Note that we’ll later need sdl2, with gles support, so let’s mark that now
echo media-libs/libsdl2 gles >> /etc/portage/package.use/libsdl2
emerge -avj --autounmask --newuse --deep @system
This may require some USE changes, if it does, hit y
to accept them, then review them via dispatch-conf
and merge them (use-new
).
12. Pick a profile
We want desktop/plasma 17.1, find it in the list, it’s currently 23
eselect profile list
eselect profile set 23
13. Time to install the desktop meta package
emerge --autounmask -avj kde-meta
Note that this will propose some USE flag changes, and requires accepting the MPEG-4 license, which is open source, but not GPL compatible.
If you want to not accept the MPEG-4 license, you can disable CD support in kdemultimedia-meta
by running
echo kde-apps/kdemultimedia-meta -cdrom >> /etc/portage/package.use/nompeg4
Regardless, accept the proposed USE changes, then review and merge them via
dispatch-conf
Note that if you want to revert the proposed changes, z
will ‘zap’ the changes, leaving you with the old version. u
is what you usually want, as it uses the proposed new version.
If you want a lighter weight install, plasma-meta
instead of kde-meta
doesn’t grab the whole suit of kde apps.
If you want something other than kde, grab the matching profile (for gnome), or the generic desktop
profile.
Then install the related meta packages, which are usually obvious with a bit of looking (e.g. eix xfce4-meta
)
With the proposed changes committed, it’s time to kick off the main install. This is going to take a while.
emerge -avj --keep-going kde-meta
Assuming it looks right, tell it to start, then go to bed. Seriously, on a low power laptop like the librem, it’ll take hours.
Note that it might fail to build everything. There are a few packages which don’t like building in parallel, and tracking down why can be incredibly difficult. If it didn’t manage to build everything, first thing to do is to try again, usually it’ll just work.
14. Build the kernel
genkernel --makeopts="-l $num_cpus -j $num_distcc_jobs" --oldconfig --menuconfig --loglevel=5 --kernel-cc=distcc --utils-cc=distcc all
That will bring up the ncurses menu configuration for the kernel. Make sure /proc/config.gz
support is enabled, and set the local version string to include where you got the config (PureOS.VERSION
) or similar. Also if you enabled the experimental
use flag, under processor type and features->processor family, set the CPU to the one matching your computer. If you aren’t using distcc, you can just set it to autodetected. If you aren’t sure what kind of CPU you have, cat /proc/cpuinfo
will tell you.
If you want zram support, enable all the related flags.
Device Drivers->Block Devices-> Compressed RAM block device
+Track zRam block satus
+ Write back incompressible or idle page
Once you are done, save it back to .config, and exit.
It will start the build all on its own, and put the results in /boot
15. fstab
Get the uuid of the root and boot partitions via
blkid /dev/sda1 -o value | head -n 1
blkid /dev/sda2 -o value | head -n 1
Edit /etc/fstab
and add the following, using the UUIDs from the preceeding
UUID=$ROOTUUID / btrfs noatime,ssd,compress=zstd:9,subvol=/root 0 1
UUID=$ROOTUUID /home btrfs noatime,ssd,compress=zstd:9,subvol=/home 0 1
UUID=$ROOTUUID /usr/local btrfs noatime,ssd,compress=zstd:9,subvol=/local 0 1
UUID=$BOOTUUID /boot vfat noatime 0 1
16. Grubbing
Install the grub-2 package,
emerge -av sys-boot/grub
Once that is done, install grub to the MBR of the hard disk.
grub-install /dev/sda
Generate the grub2 config file
grub-mkconfig > /boot/grub/grub.cfg
Verify the generated file is sane, there should be an entry for Gentoo at the very least. If it doesn’t detect the right subvolume, add
rootflags=subvol=root
to the end of the linux /kernel...
line for the Gentoo entry.
17. Don’t forget to set a passwd
passwd
18. Add a user account
emerge -av superadduser
superadduser
Follo the prompts, for additional groups, at least provide
wheel,video,audio
19. Setup auto-login
We’ll secure this later
nano /etc/inittab
Find the line starting with c1:12345
under # Terminals
Change it to
c1:12345:respawn:/sbin/agetty --skip-login --login-options "-f $your_user_name STARTW=true" 38400 tty1 linux
20. Make tty1 go straight to a graphical shell
Add the following to /home/$USER/.bashrc
if [ "$STARTW" != "" ]; then
unset STARTW
exit `~/startw`
fi
If you want X11 instead of wayland, change startw
to startx
, and configure ~/.xinitrc
accordingly.
Create /home/$USER/startw
with the following
XDG_SESSION_TYPE=wayland dbus-run-session startplasma-wayland
Set it executable
chmod +x /home/$USER/startw`
21. Reboot
Exit the chroot, unmount /dev/pts
, /dev
, /proc
, /sys
, then reboot.
22. Setup auto lock on login
echo '#!/bin/bash > ~/autolock`
echo loginctl lock-session >> ~/autolock
chmod +x ~/autolock
Add ~/autolock
to the list of startup applications in kde.
23. Setup zram
emerge -av zram-init
Then edit /etc/conf.d/zram-init
Set the number of devices to one, then find the section for device zero, and use something like the following settings
type0=swap
flag0= # The default "16383" is fine for us
size0=81920 # 80 GB of compressed data, more than this and it chokes
mlim0=2G # only 2 GB of physical memory
back0=/dev/loop0 # requries a whole block device, we'll set this up next
notr0= # keep the default on linux-3.15 or newer
maxs0=2 # maximum number of parallel processes for this device
algo0=zstd # zstd (since linux-4.18), lz4 (since linux-3.15), or lzo.
# Size: zstd (best) > lzo > lz4. Speed: lz4 (best) > zstd > lzo
labl0=zram_swap # the label name
uuid0= # Do not force UUID
args0=
Time to set up the backing device, if you want to get fancy, you can use anything for this, including network mounts or OpenCL vram devices. For simplicity, we’ll use a non-compressed file in /zram
mkdir /zram
cd /zram
touch loop0.img
btrfs property set loop0.img compression ""
dd if=/dev/zero of=loop0.img bs=1M count=10000
Now we just need to make loop0
start on startup, and make zram-init
start on startup.
Edit /etc/init.d/loop0
#!/sbin/openrc-run
depend() {
need localmount
}
start() {
ebegin "Starting loop0"
/sbin/losetup /dev/loop0 /zram/loop0.img
eend $? "Failed to start loop0"
}
stop() {
ebegin "Stopping loop0"
/sbin/losetup -d /dev/loop0
eend $? "Failed to stop loop0"
}
Then add loop0
to the need
line in /etc/init.d/zram-init
Finally
rc-update add zram-init default
to enable zram on startup.
Note that it would be best to create a new memory cgroup, and add all userspace programs to it on startup, with a memory limit 2GB less than the system memory.
That requires write access to /sys/fs/cgroup/memory
, so we’ll add a setuid helper.
Make a file called limitmem.c
with the following
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv) {
if (argc > 1) {
size_t l = strlen(argv[1]);
if (l > 5) { return 0; }
for (char idx=0; idx<l; idx++) {
if (argv[1][idx] < '0' || argv[1][idx] > '9') {
return 1;
}
}
setresuid(0, 0, 0);
system("mkdir -p /sys/fs/cgroup/memory/plasma");
system("echo 2147483648 > /sys/fs/cgroup/memory/plasma/memory.limit_in_bytes");
char tmp[] = "echo > /sys/fs/cgroup/memory/plasma/tasks";
strncpy(&tmp[5], argv[1], l);
system(tmp);
}
return 0;
}
Then compile it with
gcc limitmem.c -o limitmem
Then switch to root, own it as root, and mark it suid
su
chown root.root limitmem
chmod +s limitmem
Exit root, and add the following to the startw
script, at the top
./limitmem $$
Final thoughts
That pretty much covers the basic setup. You’ll probably want to add standard programs, like libreoffice and what not.
I’ll add a second post to describe how I have Jack set up for easy use.