Precision 5510 - Gentoo GNU/Linux

This documents all configurations, apps and tweaks to get a nicely working Linux
machine.

---

Installation
============

Partition
---------

The system was built with an existing Windows EFI partition table but this
weekend I converted it over to a luks/dmcrypt partition scheme. Thus the
table was created is as follows:

1. 200Mb ESP volume
2. 477.8G Linux filesystem

The Linux filesystem is an aes-xts-plain64 with a 512 key size.

            cryptsetup luksFormat /dev/nvme0n1p6 -c aes-xts-plain64 -s 512

After the encrypted volume is created, and opened, lvm was used to create a
444Gb partition for root and the remaining 32Gb for swap/resume. The root volume
then formatted with btrfs.

            mkfs.btrfs /dev/mapper/lvm-root

Mounting the btrfs root subvolume in the Gentoo Live install:

            mkdir /mnt/btrfs
            mount /dev/mapper/lvm-root /mnt/btrfs

Create 2 subvolumes in the / root and mount @root

            btrfs subvolume create /mnt/btrfs/\@root
            btrfs subvolume create /mnt/btrfs/\@home

            mount /dev/mapper/lvm-root /mnt/gentoo -o subvol=@root

Stage3
------

The original stage3 tarball was `stage3-amd64-systemd-20190823.tar.bz2`  
systemd was chosen so that I'm using the same init system that I need to support
for my day job.

After stage 3 is extracted, mount the home subvolume and boot volume:

            mount /dev/mapper/lvm-root /mnt/gentoo/home -o subvol=@home
            mount /dev/nvme0n1p1 /mnt/gentoo/boot

Chroot in as per the Gentoo handbook

Portage
-------

Initial portage `make.conf` setup to get going should include the following:

            COMMON_FLAGS="-march=skylake -O2 -pipe"
            VIDEO_CARDS="intel i965"
            MAKEOPTS="-j9 -l8"
            GENTOO_MIRRORS="http://ftp.swin.edu.au/gentoo"
            EMERGE_DEFAULT_OPTS="--jobs=8 --load-average=8"
            FEATURES="${FEATURES} parallel-fetch"

More settings to be discussed in __Make.conf__ section later. This is all that
is relevant for the initial install.

Kernel
------

Kernel config can be found on my [kernel-configs github
repo](https://github.com/zigford/kernel-configs/tree/master/Precision%205510)
Make it with `-j8` for all cores and after installed, edit /etc/default/grub:

            GRUB_CMDLINE_LINUX="dobtrfs rootfstype=btrfs"

Use genkernel-next to build an initramfs and install grub

            genkernel initramfs
            grub-install /dev/nvme0n1

Applications
------------

First app in vim, as it is not in Gentoo base, other handy apps for getting the
system up and running:

* app-editors/vim
* app-admin/sudo
* app-portage/eix
* app-portage/gentoolkit
* dev-vcs/git
* sys-apps/usbutils
* sys-fs/btrfsprogs
* sys-boot/os-prober
* sys-kernel/genkernel

__Note__ Genkernel pulls in sys-kernel/linux-firmware which has the binary blobs
required to get the wifi chip working on the Precision 5510.

World build
-----------

As per the Handbook, build the world, install the kernel, grub and reboot.
But! Don't forget to set the root password

First setup
===========

After first boot systemd has everything you need to get connected to the network
to get everything going. Create a file in /etc/systemd/network to setup dhcp on
eth0. Enable systemd-networkd to get going until networkmanager later.

Administration
--------------

Setup `sudo` for quicker elevation:

            vim /etc/sudoers
            
            %wheel ALL=(ALL) NOPASSWD: ALL

Useful groups
-------------

wheel   : Allows to su to root, or use sudo  
plugdev : Allows to connect to wifi as regular user and other hardware stuff  
portage : Can write into portage distfiles for testing and making ebuilds  

Sleep and hibernate
-------------------

Swap file is big enough to hold most of the RAM. Grub config is updated to
specify the swap partition UUID as the resume parameter

            GRUB_CMDLINE_LINUX="dobtrfs rootfstype=btrfs resume=UUID=9a900eaa-0312-4796-93f8-da3245add9d4"

Suspend then hibernate delay is set to 4 hours:

            vim /etc/systemd/sleep.conf

            [Sleep]
            HibernateDelaySec=240min

Lidswitch is set to suspend then hibernate

            vim /etc/systemd/logind.conf

            [Login]
            HandleLidSwitch=suspend-then-hibernate
            HandleLidSwitchDocked=ignore

Xorg and Gnome
==============

use flags for gnome added to `make.conf`

            USE="gtk bluetooth gnome -qt gdm samba acl vim readline fuse"
            L10N="en" # for dictionary in evolution

Explanation:

`fuse` is required for `gnome-gvfs` (which is a dep of gnome-base/gnome-vfs).
This makes paths mounted from gnome, visible  at /run/user/UID/gvfs

emerge gnome-base/gnome and the following apps

* gnome-base/gnome-vfs # For smb connections in nautilus
* gnome-extra/evolution-ews # Connect evolution to exchange online
* x11-terms/kitty # terminal with ligature font support
* www-client/firefox-bin

Packages for work
=================

* net-vpn/networkmanager-openconnect # vpn in networkmanager for work
* net-misc/freerdp # Rdp to servers for work
* net-misc/icaclient # Citrix client for work

Extending Gentoo
================

Apart from emerge, I'm making use of other package managers on Gentoo to
complete the environment.

Install layman

            emerge -a layman
            layman -L
            layman -a snapd
            layman -a flatpak
            layman -o http://jesseharrisit.com/overlay.xml -f -a gentoo-zigford
            emerge -a app-emulation/snapd
            emerge -a app-emulation/flatpak

            
snapd packages
--------------

            snap install chromium
            snap install teams-for-linux
            snap install p3xonenote
            snap install caprine

KVM - Qemu
==========

For virtualization, I primarily want to interface with VM's using _gnome-boxes_,
however as it lacks the sophistication for complex VM's, I also install
_virt-manager_.

Use flags for virtualization:

            app-emulation/libvirt apparmor virt-network
            app-emulation/qemu doc usbredir smartcard spice
            app-emulation/spice smartcard
            net-dns/dnsmasq script
            net-misc/spice-gtk smartcard usbredir vala

Kernel settings to enable networking in the kernel mentioned earlier.
qemu settings required for efi virtual machine

            vim /etc/libvirt/qemu.conf
            security = "none"
            nvram = [
                "/usr/share/edk2-ovmf/OVMF_CODE.fd:/usr/share/edk2-ovmf/OVMF_VARS.fd"
            ]

For a vm in boxes to run efi:

            cp /etc/libvirt/qemu.conf ~/.config/libvirt


Group memberships:

            usermod -G kvm,libvirt,qemu -a username

Tweaks to apparmor

            sed -ie 's/#include <local/include <local/' usr.sbin.dnsmasq
            vim local/usr.sbin.dnsmasq
            
            capability mknod,
            /usr/libexec/libvirt_leaseshelper rix,
            /var/lib/libvirt/dnsmasq/*.status* rw,
            /run/leaseshelper.pid rwk,
            
            vim usr.sbin.libvirt
            
            capability sys_rawio,

Set libvirt images directory to no copy on write

            chattr +C /var/lib/libvirt/images

Allow Gnome-Boxes to use libvirt's networking. Also requires user to be a member
of qemu group

            cat /etc/qemu/bridge.conf

            allow virbr0

Backups
=======

Thanks to the power of btrfs, backups are facilitated easily by snapshots.
Currently I have a systemd timer set to fire every hour. It fires a script which
does the following:

1. Mount the root btrfs volume to /mnt/btrfs (this houses 2 subvols)
2. Snapshot each subvol into /mnt/btrfs/snapshots/subvolname-yyyy-MM-dd-hh:mm:ss
3. Prune any snapshots that are not any of the following:

   * in the last 24 hours
   * daily in the last month
   * monthly until the backup drive fills to 10% free

4. If a designated backup drive is attached, transfer all snapshots
5. Delete all bar the last 2 transfered per subvolume

Finally, if the drive is not attached, when it does become available the script
is invoked with a parameter to just catch up on the snapshots.

The script can be found on
[github](https://github.com/zigford/linux-worktools/blob/master/linux/snapshot)
and the systemd timer and service look like this:

/etc/snapshots.conf

            [home]
            LocalSnapshots=/mnt/btrfs/snapshots
            RemoteSnapshots=/run/media/harrisj/7cb22d51-b8a7-45ee-b1a3-2f3db51c931f
            SubvolumeRoot=/home

            [root]
            LocalSnapshots=/mnt/btrfs/snapshots
            RemoteSnapshots=/run/media/harrisj/7cb22d51-b8a7-45ee-b1a3-2f3db51c931f
            SubvolumeRoot=/


snapshot.service

            [Unit]
            Description=Take a BTRFS Snapshot of all the volumes

            [Service]
            Type=simple
            ExecStart=/usr/local/bin/snapshot

snapshot.timer

            [Unit]
            Description=Timer file for snapshot unit. Snapshots hourly and continually prunes

            [Timer]
            OnCalendar=*-*-* *:00:00
            Persistent=true

            [Install]
            WantedBy=timers.target

backup-snapshots.service

            [Unit]
            Description=Backup snapshots when backup drive is attached
            Requires=run-media-harrisj-7cb22d51\x2db8a7\x2d45ee\x2db1a3\x2d2f3db51c931f.mount
            After=run-media-harrisj-7cb22d51\x2db8a7\x2d45ee\x2db1a3\x2d2f3db51c931f.mount

            [Service]
            ExecStart=/usr/local/bin/snapshot -b

            [Install]
            WantedBy=run-media-harrisj-7cb22d51\x2db8a7\x2d45ee\x2db1a3\x2d2f3db51c931f.mount

Docker
======

Docker's default IP range conflicts with works DNS.
The following file switches it to another address range.

            cat /etc/docker/daemon.json
            {
                "bip": "192.168.12.5/24",
                "fixed-cidr": "192.168.12.5/25",
                "fixed-cidr-v6": "2001:db8::/64",
                "mtu": 1500
            }

Wifi off on ethernet
====================

In my shed the wifi is weak. I'm on wired here, so don't need the wifi.
Thankfully NetworkManager offers ability to run scripts when connections change.

            cat /etc/NetworkManager/dispatcher.d/wired_only.sh
            #!/bin/sh

            IF=$1
            STATUS=$2

            if echo "$IF" |grep -q enp0s20f0u2u1i5
            then
                case "$2" in
                    up)
                        logger -s "ethernet up killing wifi"
                        rfkill block 1
                    ;;
                    down)
                        logger -s "ethernet down, raising wifi"
                        rfkill unblock 1
                    ;;
                    *)
                    ;;
                esac
            fi

Automatically stop and start DisplayLink manager
================================================

At home, I'm using a Targus USB 3.0 dock to connect to two monitors. It's pretty
convinient but it does use a few extra joules of battery (as shown by powertop).

Instead of manually stopping and starting the dlm service. I can use systemd and
udev rules to run the service only when the device is attached.

            cat /etc/udev/rules.d/99-displaylink.rules
            ACTION=="add", ATTRS{idProduct}=="4306", ATTRS{idVendor}=="17e9", ENV{SYSTEMD_WANTS}="dlm.service"

This rule will start `dlm` when the usb device is detected. The following
alteration to the systemd unit for dlm ensures that when the device is removed,
the service is stopped.

            systemctl cat dlm
            # /lib/systemd/system/dlm.service
            [Unit]
            Description=DisplayLink Manager Service
            After=display-manager.service
            Conflicts=getty@tty7.service

            [Service]
            ExecStartPre=/sbin/modprobe evdi
            ExecStart=/opt/displaylink/DisplayLinkManager
            Restart=always
            WorkingDirectory=/opt/displaylink
            RestartSec=5

            [Install]
            WantedBy=graphical.target

            # /etc/systemd/system/dlm.service.d/override.conf
            [Unit]
            BindsTo=sys-subsystem-net-devices-enp0s20f0u2u1i5.device
            StopWhenUnneeded=true

**Note** that the alterations are configured using `systemctl edit dlm`

Tags: gentoo, btrfs, linux 
