Tag Archives: Gentoo

GitWeb

Emerge git with the required USE flags:

emerge -aq dev-vcs/git curl gpg iconv nls pcre perl safe-directory webdav cgi cvs highlight keyring tk

Configure Apache vhosts (NO AUTH):

<VirtualHost *:443>
	  SSLEngine on
        <FilesMatch "\.(cgi|shtml|phtml|php)$">
          SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory "/var/www/localhost/cgi-bin">
          SSLOptions +StdEnvVars
        </Directory>
          SSLCertificateFile /path/to/cert.crt
          SSLCertificateKeyFile /path/to/key.key
          ServerName git.example.com
          DocumentRoot /usr/share/gitweb
	  Options ExecCGI FollowSymLinks SymLinksIfOwnerMatch
	<Location />
	  SSLRequireSSL
	  Require all allowed
          RewriteOptions inherit
          AllowOverride All
	</Location>
        <Directory /usr/share/gitweb>
          Require all granted
          RewriteOptions inherit
          AllowOverride All
          Options ExecCGI FollowSymLinks SymLinksIfOwnerMatch
          <Files gitweb.cgi>
            SetHandler cgi-script
          </Files>
        </Directory>
	  DirectoryIndex gitweb.cgi
          SetEnv  GITWEB_CONFIG  /etc/gitweb.conf
        <IfModule headers_module>
          RequestHeader set X-HTTPS 1
        </IfModule>
</VirtualHost>

Basic /etc/gitweb.conf
$projectroot = '/path/to/gitroot';
@git_base_url_list = ( 'git@example.com', );
$site_name = "Smack my git up!";
$default_projects_order = "age";
$projects_list_group_categories = 1;
$feature{'blame'}{'default'} = [1];
$feature{'highlight'}{'default'} = [1];

Adjust git-daemon
Gitweb allows browsing repositories via HTTP, but if you will be pulling from your repositories using the git:// protocol, you'll also want to run git-daemon. On Gentoo, this is really easy, just edit /etc/conf.d/git-daemon as you see fit. eg:

GITDAEMON_OPTS="--syslog --enable=receive-pack --export-all"

This exports all repositories within the git root. It also allows pushing file to the server.

You will also need to ensure that any clients to connect to port tcp/9418 (default)

Setup the git user

useradd -m git -d /path/to/githome -s /usr/bin/git-shell
mkdir /path/to/githome/.ssh
cat /home/A_USER/.ssh/id_rsa.pub > /path/to/githome/.ssh/authorized_keys
chmod 700 /path/to/githome/.ssh
chmod 600 /path/to/githome/.ssh/authorized_keys
setfacl -PRdm u:apache:rwx /path/to/githome

Create an Empty Repository

su -s /bin/bash git
cd
mkdir name.git
cd name.git
git init --bare
echo "This is a test" > description
git remote add origin git@example.com:name.git

Set Configuration Options

Execute the following on a client (optional)
To see available options execute: git help --config

git config --global init.defaultBranch master
git config --global core.editor vim
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.up rebase
git config --global alias.ci commit
git config --global user.name "A_USER"
git config --global user.email A_USER@example.com
git config --global color.ui true
git config --global --add --bool push.autoSetupRemote true

Clone Repo

cd to local git
git clone git@example.com:name.git
cd name
touch README.md
git add README.md
git ci -m "Initial Setup"
git push
git br branch_name
git co branch_name
mkdir testdir
touch testdir/testfile
git add .
git ci -m "init"
git push # Pushes to your upstream branch
git push origin branch_name:master # Pushes to the master branch

Web Authentication

Note: I did not have any success using dbmmanage. Use htdbm instead.

Create the database file and add a user:
Do not store this in the root of web eg: /var/www/locahost/htdocs, but make sure apache can get to the file.

htdbm -cm -TGDBM <path/to/dbm_file> <user>

-c - create db
-m - use MD5 hashing
-T - set the format of the db file

Set the permission for apache:

chown apache: <path/to/dbm_file>
chmod 640 <path/to/dbm_file>

Add code to vhosts:
You can apply this to files, directories etc. Here I've done it for the whole subdomain. Replace the 3 highlighted italic lines above with the code below, excluding the start/end tags.

    <Location />
      AuthName "Private"
      AuthType Basic
      AuthBasicProvider dbm
      AuthDBMType GDBM
      AuthDBMUserFile "/path/to/dbm_file"
      Require valid-user 
      Require all denied
      RewriteOptions inherit
      AllowOverride All
    </Location>

Reload apache and browse to protected area and you should be prompted to authenticate.

A good explanation can be found here for the web config.

Apache Custom LogFormats

Take the leg work out of reading your apache logs by converting them to a structured format that's easy to read. Enter JSON :)

Create the file /etc/apache2/vhosts.d/00_default_logging.conf
You will also need to ensure the "logio_module" is enabled.

For the access log, I use the format: Apache doc.

LogFormat "{\"time\":\"%{msec}t\", \"bytes_in\":\"%I\", \"bytes_out\":\"%O\", \"cookie\":\"%{Cookie}i\", \"server\":\"%v\", \"dest_port\":\"%p\", \"http_content_type\":\"%{Content-type}i\", \"http_method\":\"%m\", \"http_referrer\":\"%{Referer}i\", \"http_user_agent\":\"%{User-agent}i\", \"ident\":\"%l\", \"response_time_microseconds\":\"%D\", \"client\":\"%h\", \"remoteAddr\":\"%a\", \"status\":\"%>s\", \"uri_path\":\"%U\", \"uri_query\":\"%q\", \"user\":\"%u\"}" apache_json

And for the error log, I use: Apache doc.

ErrorLogFormat "{\"time\":\"%{msec}t\", \"client\":\"%a\", \"log_level\":\"%l\", \"pid\":\"%P\", \"srcln\":\"%F\", \"error_code\":\"%E\", \"message\":\"%M\"}"

In the vhost.conf I have the following at the bottom of my VirtualHost block:

<VirtualHost>
    ...
    CustomLog "/var/log/apache2/ssl_access.log" apache_json
    ErrorLog /var/log/apache2/ssl_error.log
</VirtualHost>

Give the command to test the config is sane:

apachectl configtest

If nothing is returned, go ahead and restart apache.
This also makes importing the logs much easier into tools like ELK or Splunk.

Gentoo Install with LVM/EFI via Ansible

Assumptions: You have a host with Ansible and a network.

Download the Gentoo iso from here.
Download the role from here.

You will need to edit:
gentoobase/vars/main.yml - encrypt password

Boot with the ISO (cached), ensuring that networking is present.

Once booted, set a password and start the ssh daemon.

Unmount the ISO.

SSH as the root user to the target server.
mkdir .ssh
Copy the pubkey of the user executing the playbook into /root/.ssh/authorized_keys

CD to your playbook role directory.
Unpack the role tarball
Create the playbook below.

Playbook

---
- name: Base Gentoo Installation
gather_subset: min
hosts: vms
tasks:
- import_role:
name: gentoobase
...
 ansible-playbook -u root gentoo_install_base.yml

This will take ~3 hours to complete the base system.

Timings are based on a VM (i7 6700K x4, 16Gb RAM)

If you wish to change any settings, edit:
roles/gentoobase/vars/main.yml

Now go outside and get some fresh air.

The below is to understand the build process.

Manual Steps

Partition the HDD:
gdisk /dev/Xda
part1 = 512M 8300 [boot]
part2 = 100M ef00 efi [efi]
part3 = LVM 8e00 [LVM]
part4 = 4G 8200 [swap]

Create LVMs:

pvcreate /dev/Xda2
vgcreate vg00 /dev/Xda2
lvcreate -L 20G -n root vg00
lvcreate -L 10G -n home vg00

Format FileSystems:

mke2fs -t ext4 -L BOOT /dev/Xda1
mkfs.vfat -F 32 -n EFI /dev/Xda2
mke2fs -t ext4 -L ROOT /dev/mapper/vg00-root
mke2fs -t ext4 -L HOME /dev/mapper/vg00-home

Mount FileSystems:

mount -t ext4 /dev/mapper/vg00-root /mnt/gentoo
mkdir -p /mnt/gentoo/boot/EFI
mount -t ext4 /dev/vda1 /mnt/gentoo/boot
mount -t vfat /dev/vda2 /mnt/gentoo/boot/EFI
mount swap if configured

SCP the stage3 and portage files to the VM

Download Tarballs:

wget https://distfiles.gentoo.org/releases/amd64/autobuilds/current-stage3-amd64-systemd/stage3-amd64-systemd-20240616T153408Z.tar.xz

wget https://gentoo.osuosl.org/snapshots/portage-latest.tar.xz

Unpack files:

tar xpf stage3...xz -C /mnt/gentoo
tar xpf portage-latest...xz -C /mnt/gentoo/usr/

Mount Some More FileSystems:

mount -t proc /proc /mnt/gentoo/proc
mount --rbind /sys /mnt/gentoo/sys
mount --make-rslave /mnt/gentoo/sys
mount --rbind /dev /mnt/gentoo/dev
mount --make-rslave /mnt/gentoo/dev
mount --rbind /run /mnt/gentoo/run
mount --make-rslave /mnt/gentoo/run
test -L /dev/shm && rm /dev/shm && mkdir /dev/shm
mount -t tmpfs -o nosuid,nodev,noexec shm /dev/shm
chmod 1777 /dev/shm

Setup Rsync Mirror:

mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf

DNS:
cp -L /etc/resolv.conf /mnt/gentoo/etc/resolv.conf

Setup Portage:

mkdir /mnt/gentoo/var/db/repos/gentoo
mkdir /mnt/gentoo/etc/portage/repos.conf
nano -w /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
[DEFAULT]
main-repo = gentoo
[gentoo]
location = /usr/portage
sync-type = rsync
sync-uri = rsync://rsync.europe.gentoo.org/gentoo-portage

Chroot into the VM:

chroot /mnt/gentoo /bin/bash
env-update
source /etc/profile

Set Locale:

ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime
nano -w /etc/locale.gen
    en_GB.UTF-8 UTF-8
Execute locale-gen

Set Profile:

eselect profile list (choose the number in brackets)
"[30]  default/linux/amd64/23.0/no-multilib/systemd (stable)"
eselect profile set 30

Let's Start Building:

emerge -av gentoo-sources
ln -s /usr/src/linux-<version>-gentoo /usr/src/linux
cd /usr/src/linux
make defconfig && make && make modules_install
cp arch/x86_64/boot/bzImage /boot/kernel-<version>
cp .config /boot/config-<version>-gentoo (optional)
cpan Locale::gettext
emerge -q vim genkernel grub lvm2 gptfdisk efibootmgr

Setup Grub:

grub-install --target=x86_64-efi --efi-directory=/boot/EFI /dev/Xda
vi /etc/default/grub
    GRUB_CMDLINE_LINUX="rootfstype=ext4 init=/usr/lib/systemd/systemd dolvm"

Update fstab:

blkid
Copy the UUID for /boot and /
UUID1=$(blkid | grep Xda1 | grep -Po "(UUID.*?)\"\s")
UUID2=$(blkid | grep Xda2 | grep -Po "(UUID.*?)\"\s")
echo -e "${UUID1}\t/boot\text4\tdefaults\t1 2" >> /etc/fstab
echo -e "${UUID2}\t/\text4\tdefaults\t1 1" >> /etc/fstab
cd /etc/
cp -p genkernel.conf genkernel.conf.orig
vi genkernel.conf

uncomment:
MAKEOPTS="$(portageq envvar MAKEOPTS)"
LVM="yes"

genkernel initramfs --lvm (this does not overwrite the kernel above)
grub-mkconfig -o /boot/grub/grub.cfg

passwd

emerge -q networkmanager gentoolkit gpm
systemctl enable sshd NetworkManager

2FA for SSH/GDM

Please emerge qrencode and google-authenticator-libpam-hardened.
At the time of writing this, you have to install the MASKED version.

Ensure that your terminal is 90x56 to retain the QR code.

ACCEPT_KEYWORDS="**" emerge -av google-authenticator-libpam-hardened

These are the packages that would be merged, in order:

Calculating dependencies… done!
[ebuild N ] sys-auth/oath-toolkit-2.6.2-r2::gentoo USE="pam -pskc -static-libs -test" 4,196 KiB
[ebuild N ] sys-auth/google-authenticator-libpam-hardened-9999::gentoo USE="qrcode" 0 KiB

Execute google-authenticator as the user

$ google-authenticator

Do you want authentication tokens to be time-based (y/n) y



Your new secret key is: jeronimo!
Your potential verification codes are 012345 012345 012345 012345 012345
Your emergency scratch codes are:
  88888888
  88888888
  88888888
  88888888
  88888888

Do you want me to update your "/home/<user>/.google_authenticator" file? (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) y

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n) y

Open /etc/pam.d/system-login with your editor and add these 2 lines at the bottom:

auth required pam_google_authenticator.so nullok
auth required pam_permit.so

Configure SSHD

Open /etc/sshd/sshd_config in your editor and ensure the following settings are present.

PubkeyAuthentication no
PasswordAuthentication yes
UsePAM yes
ChallengeResponseAuthentication yes

Note: If pubkey is enabled, it will override 2FA completely.

GDM

Editing /etc/pam.d/system-login as above should be enough, just restart the gdm service :)
You'll use your normal password and then be prompted for your 2FA code.

QR Codes

You can generate your own QR codes on the cli and output to screen or image file.

qrencode -t ansi -l H -o - <STRING>

will output to screen.

 qrencode -s30 -l H -o qrcode.png <STRING>

will output to png.

Gentoo CPU Microcode

Here we will get the firmware for the CPU loaded at boot.  This helps the stability and efficiency of the processor.

Let's make sure we have the required options enabled in the kernel and rebuild if not.

General setup  --->
    [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
Processor type and features  --->
    <*> CPU microcode loading support
    [*]   Intel microcode loading support

If these were not enabled, enable them as above (not modules!) and recompile and install your kernel.

Next we'll install 2 packages required for this to work.

# emerge -av intel-microcode iucode_tool

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild R ] sys-firmware/intel-microcode-20161104::gentoo USE="split-ucode -initramfs -monolithic" 0 KiB
[ebuild R ] sys-apps/iucode_tool-2.1.1::gentoo 0 KiB

Mount your /boot filesystem and execute the following to generate the cpio archive.

iucode_tool -S --write-earlyfw=/boot/early_ucode.cpio /lib/firmware/intel-ucode/*

You should see output like this with a different HEX value.

iucode_tool: system has processor(s) with signature 0x000206a7
iucode_tool: Writing selected microcodes to: /boot/early_ucode.cpio

Now we'll configure grub2 and install the new boot config.

Open the file /etc/grub.d/10_linux in your favourite editor and (at line ~204) make the following change.

From this:

initrd=
  for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
           "initrd-${version}" "initramfs-${version}.img" \
           "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
           "initrd-${alt_version}" "initramfs-${alt_version}.img" \
           "initramfs-genkernel-${version}" \
           "initramfs-genkernel-${alt_version}" \
           "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
           "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
    if test -e "${dirname}/${i}" ; then
      initrd="$i"
      break
    fi
  done

To:

 initrd=
 for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \
  	   "initrd-${version}" "initramfs-${version}.img" \
  	   "initrd.img-${alt_version}" "initrd-${alt_version}.img" \
  	   "initrd-${alt_version}" "initramfs-${alt_version}.img" \
  	   "initramfs-genkernel-${version}" \
  	   "initramfs-genkernel-${alt_version}" \
  	   "initramfs-genkernel-${GENKERNEL_ARCH}-${version}" \
  	   "initramfs-genkernel-${GENKERNEL_ARCH}-${alt_version}"; do
 if test -e "${dirname}/${i}" ; then
 initrd="early_ucode.cpio ${rel_dirname}/$i"
 break
 else
 initrd="early_ucode.cpio"
 fi
 done

Edit /etc/default/grub (at line ~59)

# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to kernel
GRUB_DISABLE_LINUX_UUID=true

And last off, install the new grub config:

grub-mkconfig -o /boot/grub/grub.cfg

And that is it!

If there is an update to sys-firmware/intel-microcode from this point that contains firmware for your CPU, just mount your boot FS and execute the iucode_tool command to generate a new cpio archive.

Greylisting with Exim

I decided to apply greylisting on my server, not because I had to as spamassassin was blocking 99.999999999% of spam, but because I can ;)

I set this up on Exim-4.88 which was the current stable release at the time of writing.

It actually easier than I thought.

Under the "MAIN CONFIGURATION SETTINGS" I added the following line to define my whitelist:

addresslist whitelist_senders = wildlsearch;/etc/exim/greylist_whitelist

The file should contain either full email addresses or wildcard domains.  eg this@email.com or *@email.com on separate lines.

Then under the "ACL CONFIGURATION" section, I have the following.  This precedes the spam section of my config.

warn set acl_m_greyfile = /var/spool/exim/greylist/${length_255:\
${sg{$sender_host_address}{\N\.\d+$\N}{}},\
${sg{$sender_address,$local_part@$domain}{\N[^\w.,=@-]\N}{} }}

defer log_message = greylisted
!senders = +whitelist_senders
condition = ${if exists{$acl_m_greyfile}\
{${if >{${eval:$tod_epoch-\
${extract{mtime}{${stat:$acl_m_greyfile}} }}\
}{180}{0}{1}}\
}{${if eq{${run{/usr/bin/touch $acl_m_greyfile} }}{}{1}{1} }} }
message = Deferred: Temporary error, please try again later

The "!senders = +whitelist_senders" line will lookup against the file you created.  It will also create an empty file within the path of the first line of this section for the time based rejection.  So to keep things "tidy", we'll run a cronjob every 30 mins to remove files.

# Expire greylisters
*/30 * * * * /usr/bin/find /var/spool/exim/greylist -cmin +363 -type f -delete

And that's it!  Restart exim, send an email from an outside source and check your exim log ;)

2017-01-01 12:49:44 H=(209-182-113-49.ip.twinvalley.net) [209.182.113.49] F=<czgxi@biz2net.com> temporarily rejected RCPT <this@email.com>: greylisted

If the mail is from a genuine and correctly configured email server, when it retries (after 3 minutes), the mail will be accepted ;)

Here are some visualisations to show how effective greylisting is.

This is a graph showing the number of spam blocked every day.

Spam blocked
Can you guess when I applied greylisting?

This is a graph showing the grey listing applied every day and how it actually reduces the number of spam emails received by the server.

Greylisting in effect
Greylisting in effect!

Raspberry Pi 3B Gentoo Install

Raspberry_Pi_Logo.svg

NOTE:  Although the CPU is 64bit, the rest of it is 32bit.  Trying to run in 64bit will cause pain and suffering.

Other NOTE:  I cannot YET get the display to work with hardware acceleration.  Blank screen when enabled and kodi goes nuts, writing hundreds of lines to the log per second.

15:24:07 T:1943678976 ERROR: Previous line repeats 1 times.
15:24:07 T:1943678976 ERROR: Invalid GUI Shader selected - [guishader_frag_fonts.glsl]
15:24:07 T:1943678976 ERROR: Invalid GUI Shader selected - [guishader_frag_texture_noblend.glsl]

Contents:

Partition SD
Boot
Root
Portage
Get a few things sorted
Screen
Offbox Building
Time to get compiling!
Distcc Server
Distcc Client
Systemd
WIFI
Locale
Hostname
Keymap
Tweaks
Caveats
Kodi
Mame

Partition SDtop

Example setup:

# fdisk -H255 -S63 /dev/sdX
--------------------------------------------------------------------------------
Disk /dev/sdg: 59 GiB, 63367544832 bytes, 123764736 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device Boot Start End Sectors Size Id Type
/dev/sdg1 * 2048 104447 102400 50M c W95 FAT32 (LBA)
/dev/sdg2 104448 115447807 115343360 55G 83 Linux
/dev/sdg3 115447808 123764735 8316928 4G 5 Extended
/dev/sdg5 115449856 123764735 8314880 4G 82 Linux swap / Solaris
--------------------------------------------------------------------------------

Format Filesystems:

mkfs.vfat -n BOOT /dev/sdg1
mke2fs -t ext4 -L ROOTFS /dev/sdg2
mkswap /dev/sdg5

The boot filesystem needs to be VFAT but the rest are up to you :)


Boot!top

Download the firmware archive from here

extract the /boot/* to the boot filesystem of the SD card.

Create a file called cmdline.txt to specify any necessary kernel parameters.
For example:

root=/dev/mmcblk0p2 rootdelay=2 rootfstype=ext4 rootwait

Create the file config.txt for more options.
For example:

gpu_mem=64 arm_control=0x200

That should be the boot system sorted :)


Roottop

Download stage3
stage3-armv7a_hardfp-YYYYMMDD.tar.bz2

Download portage

Unpack the stage3 tarball:

tar xpjf stage3-arm64-YYYYMMDD.tar.bz2 -C /path/to/sd/ROOTFS

Adjust the make.conf file:

/path/to/sd/ROOTFS/etc/portage/make.conf

CFLAGS="-O2 -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard"
CXXFLAGS="${CFLAGS}"

Generate the root password hash:

openssl passwd -1

Add this to the /path/to/sd/ROOTFS/etc/shadow file

eg (replace the * between the first and second :)

root:$1$SnXkVgp0$AhbB/IogzcV.opa9suOx21:9797:0:::::

Adjust the /path/to/sd/ROOTFS/etc/fstab file. The SD card is recognized as /dev/mmcblk0

<fs> <mountpoint> <type> <opts> <dump> <pass>
/dev/mmcblk0p1 /boot vfat noauto,noatime 0 0
/dev/mmcblk0p2 / ext4 noatime 0 1
/dev/mmcblk0p3 none swap sw 0 0

Portagetop

Unpack the portage tarball:

tar xpjf /path/
to/Downloads/portage-latest.tar.bz2 -C /path/to/sd/ROOTFS/usr/

At this point we should now have a bootable RPi3. :)  It can't do very much, but we'll work on that.

Hint: Boot up the RPi


Get a few things sortedtop

Once booted and logged in, do this before we do anything else.

Get the network up:

Assuming the use of DHCP on the eth0 network interface.

cd /etc/init.d/
cp net.lo net.eth0
rc-config start net.eth0
rc-update add net.eth0 boot
rc-update add sshd default

If you intend on doing remotely, we need to create a user and assign to the wheel group.  We could configure SSH to accept direct root connections, but that's bad practice.

execute the command:

useradd -m <username> -G wheel

This will create the user, the home directory and amend the assigned groups with the wheel group.

Now set the passwd:

passwd <username>

Edit rc.conf

nano /etc/rc.conf

uncomment rc_sys=""

Stop the annoying "s0 respawning too fast" error:

nano /etc/inittab

Comment the s0:12345... line

The RaspberryPi does not have a hwclock:

rc-update add swclock boot
rc-update del hwclock boot

Set a hostname (optional unless you run your own DHCP/DNS)

nano -w /etc/conf.d/hostname
hostname="pifukka"

Set the correct keymap for the console.

nano -w /etc/conf.d/keymaps
set keymap="uk"

Set the correct timezone

ln -sf /usr/share/zoneinfo/Europe/London /etc/localtime

Create the portage directories.

mkdir /etc/portage/package.{keywords,mask,use}

Until we have NTP installed and working, each time the RPi is booted, we'll need to set the time/date.  This is done by executing:

date --set="04/09/2016 19:55:00"

MM/DD/YYYY HH:MM:SS

Failure to do this will cause pain if you try and compile anything.  eg distcc goes into a configure loop :(

Select the profile of the OS:

Execute:

eselect profile list

will get you this:

 [1] default/linux/arm/13.0
 [2] default/linux/arm/13.0/desktop
 [3] default/linux/arm/13.0/desktop/gnome
 [4] default/linux/arm/13.0/desktop/gnome/systemd
 [5] default/linux/arm/13.0/desktop/kde
 [6] default/linux/arm/13.0/desktop/kde/systemd
 [7] default/linux/arm/13.0/developer
 [8] default/linux/arm/13.0/armv4
 [9] default/linux/arm/13.0/armv4/desktop
 [10] default/linux/arm/13.0/armv4/desktop/gnome
 [11] default/linux/arm/13.0/armv4/desktop/kde
 [12] default/linux/arm/13.0/armv4/developer
 [13] default/linux/arm/13.0/armv4t
 [14] default/linux/arm/13.0/armv4t/desktop
 [15] default/linux/arm/13.0/armv4t/desktop/gnome
 [16] default/linux/arm/13.0/armv4t/desktop/kde
 [17] default/linux/arm/13.0/armv4t/developer
 [18] default/linux/arm/13.0/armv5te
 [19] default/linux/arm/13.0/armv5te/desktop
 [20] default/linux/arm/13.0/armv5te/desktop/gnome
 [21] default/linux/arm/13.0/armv5te/desktop/kde
 [22] default/linux/arm/13.0/armv5te/developer
 [23] default/linux/arm/13.0/armv6j
 [24] default/linux/arm/13.0/armv6j/desktop
 [25] default/linux/arm/13.0/armv6j/desktop/gnome
 [26] default/linux/arm/13.0/armv6j/desktop/kde
 [27] default/linux/arm/13.0/armv6j/developer
 [28] default/linux/arm/13.0/armv7a *
 [29] default/linux/arm/13.0/armv7a/desktop
 [30] default/linux/arm/13.0/armv7a/desktop/gnome
 [31] default/linux/arm/13.0/armv7a/desktop/kde
 [32] default/linux/arm/13.0/armv7a/developer
 [33] hardened/linux/arm/armv7a
 [34] hardened/linux/arm/armv6j
 [35] hardened/linux/musl/arm/armv7a
 [36] default/linux/uclibc/arm/armv7a
 [37] hardened/linux/uclibc/arm/armv7a

As you can see by the `*`, I have left it at the default (option 28)

We are going to be required to build a few packages natively on the RPi3.  This will take a while due to the ARM CPU having to compile power of a decomposing turd :|

I also found it useful to get screen installed :)  Should take approx.  5 minutes.

emerge app-misc/screen

Screentop

I find screen extremely useful.  I'm sure you had situations where you were part way through something on a remote terminal and you gotten disconnected and lost everything.  With screen, that doesn't matter.  If you get disconnected, just reconnect to the server then reconnect to the screen session. :)

start a screen session

screen -S sesh1

Offbox Buildingtop

We are going to configure both the RPi and full fat system as a server/client compiler array as compiling anything on the RPi is beyond time and space.

SERVER:top

CROSSDEV

Add the crossdev package to keywords to install the latest version.

If you need to remove cross building:

execute crossdev -C cross-armv7a-hardfloat-linux-gnueabi

* Uninstalling target 'armv7a-hardfloat-linux-gnueabi' ...
<<< cross-armv7a-hardfloat-linux-gnueabi/glibc-2.22-r4
<<< cross-armv7a-hardfloat-linux-gnueabi/linux-headers-4.3
<<< cross-armv7a-hardfloat-linux-gnueabi/binutils-2.25.1-r1
PORTAGE_BZIP2_COMMAND setting is invalid: 'bzip2'
PORTAGE_BZIP2_COMMAND setting from make.globals is invalid: 'bzip2'
<<< cross-armv7a-hardfloat-linux-gnueabi/gcc-4.9.3
/usr/armv7a-hardfloat-linux-gnueabi: directory still exists; remove recursively? [y/N]

Then reverse the steps below.

emerge crossdev

Tell portage about our repo.

mkdir -p /usr/local/portage-crossdev/{profiles,metadata}
echo 'portage-crossdev' > /usr/local/portage-crossdev/profiles/repo_name
echo 'masters = gentoo' > /usr/local/portage-crossdev/metadata/layout.conf
chown -R portage:portage /usr/local/portage-crossdev

vi /etc/portage/repos.conf/gentoo.conf
[portage-crossdev]
location=/usr/local/portage-crossdev
masters=gentoo
priority=10

Build the Toolchain:

crossdev -S -v -t armv7a-hardfloat-linux-gnueabi

You should get the following output:

--------------------------------------------------------------------------------
 * crossdev version: 20160602
 * Host Portage ARCH: amd64
 * Target Portage ARCH: arm
 * Target System: armv7a-hardfloat-linux-gnueabi
 * Stage: 4 (C/C++ compiler)
 * ABIs: default

* binutils: binutils-[stable]
 * gcc: gcc-[stable]
 * headers: linux-headers-[stable]
 * libc: glibc-[stable]

* CROSSDEV_OVERLAY: /usr/local/portage-crossdev
 * PORT_LOGDIR: /var/log/portage
 * PORTAGE_CONFIGROOT: 
 * Portage flags: -v
 _ - ~ - _ - ~ - _ - ~ - _ - ~ - _ - ~ - _ - ~ - _ - 
 * leaving metadata/layout.conf alone in /usr/local/portage-crossdev
 _ - ~ - _ - ~ - _ - ~ - _ - ~ - _ - ~ - _ - ~ - _ - 
 * Log: /var/log/portage/cross-armv7a-hardfloat-linux-gnueabi-binutils.log
 * Emerging cross-binutils ...

These are the packages that would be merged, in order:

Calculating dependencies

--------------------------------------------------------------------------------
THIS IS WHERE SHIT GETS BUILT!

NOTE:
If everything fails with the following error, that means you borked the setup eg NOT FOLLOWED THE INSTRUCTIONS ;).

Calculating dependencies /usr/lib/portage/python3.4/ebuild.sh: line 624:
 /path/to/sd/ROOTFS/usr/local/portage-crossdev/cross-aarch64-unknown-linux-gnu/binutils/binutils-9999.ebuild:
 Permission denied

DISTCCD

Add "sys-devel/distcc crossdev" to /etc/portage/package.use/package.use

emerge  distcc

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild N ] sys-devel/distcc-3.2_rc1-r4::gentoo USE="crossdev ipv6 -avahi -gnome -gssapi -gtk -hardened (-selinux) -xinetd" PYTHON_TARGETS="python2_7" 0 KiB

----------------------------------------------------------
INITRC:
/etc/conf.d/distccd

DISTCCD_OPTS="${DISTCCD_OPTS} --allow 192.168.0.0/24"
----------------------------------------------------------
SYSTEMD:
/etc/systemd/system/distccd.service.d/00gentoo.conf

[Service]
Environment="ALLOWED_SERVERS=192.168.0.0/24"
----------------------------------------------------------

This can be space separated IPs.

/etc/distcc/hosts
just IPs of the clients. eg 192.168.0.1,cpp,lzo

CLIENT:top

DISTCC

emerge distcc

Takes approx. 5 minutes.

execute distcc-config --set-hosts "<build_host>,cpp,lzo"

Once installed add `FEATURES="distcc distcc-pump"` to /etc/portage/make.conf.

Also add `MAKEOPTS="-jX -lX"` to /etc/portage/make.conf where `jX` is the number of CPUs on the build server times 2+1 and lX is the number of CPUs on the client.

eg MAKEOPTS="-j17 -l4"

Edit /etc/portage/make.conf and add EMERGE_DEFAULT_OPTS="--jobs=8 --load-average=1" (optional)

NOTE: Although the main work is now off loaded, all the pre and post compile work is still done natively.


Time to get compiling!top

Install a time daemon.

pump emerge ntp

(2 packages & approx. 12 minutes)

Auto start ntp.

rc-update add ntp-client default
/etc/init.d/ntp-client start

KERNEL:

We're going to need this at some point.  Some applications need a kernel source to compile.  This should be relatively painless now we have a build server.  Compiling natively takes ~6 hours!

You will need to add sys-kernel/raspberrypi-sources ** to package.keywords

pump emerge raspberrypi-sources

This will download an uncompressed kernel source from git ~1.45Gb.  That and about 21 other deps that take roughly 2 hours to install (not including kernel build).

cd /usr/src/linux-4.4.9999-raspberrypi

CROSSDEV ONLY!!!

x64:

make ARCH=arm64 defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu- oldconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu-
make ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnu- modules_install INSTALL_MOD_PATH=/run/media/cdstealer/ROOTFS

NOTE: Ensure python2.7 is enabled as >=3.4 gets the error
"TypeError: 'str' does not support the buffer interface"

imagetool-uncompressed.py arch/arm/boot/Image /run/media/cdstealer/BOOT/boot/kernel.img

x32:

make ARCH=arm bcm2709_defconfig
make ARCH=arm CROSS_COMPILE=armv7a-hardfloat-linux-gnueabi- oldconfig
make ARCH=arm CROSS_COMPILE=armv7a-hardfloat-linux-gnueabi- -j$(nproc)
make ARCH=arm CROSS_COMPILE=armv7a-hardfloat-linux-gnueabi- modules_install INSTALL_MOD_PATH=/run/media/cdstealer/ROOTFS
cp arch/arm/boot/zImage /run/media/cdstealer/BOOT/boot/kernel.img

NATIVE:

make bcm2709_defconfig
make
make modules_install
cp arch/arm/boot/zImage /boot/kernel.img

Another way is by the official docs:

make -j4 zImage modules dtbs
cp arch/arm/boot/dts/*.dtb /boot/
cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
cp arch/arm/boot/dts/overlays/README /boot/overlays/
scripts/mkknlimg arch/arm/boot/zImage /boot/kernel7.img
make modules_install

Which should then output:

Version: Linux version 4.4.19-raspberrypi-v7+ (root@pifukka) (gcc version 4.9.3 (Gentoo 4.9.3 p1.5, pie-0.6.4) ) #3 SMP Wed Sep 7 00:07:23 BST 2016
DT: y
DDT: y
270x: y
283x: n

With a slightly modified config (I removed most drivers not relevant to me.  This is the config I used (4.4.21-raspberrypi-v7+) and got a compile time of 1 hour!!  So the config is mainly to power the bare RPi3b, a MCE remote and a Playstation controller.

Executed this:

ks=$(date); make -j4 zImage modules dtbs; kf=$(date) && cp arch/arm/boot/dts/*.dtb /boot/ && cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/ && cp arch/arm/boot/dts/overlays/README /boot/overlays/ && scripts/mkknlimg arch/arm/boot/zImage /boot/kernel7-custom.img && make modules_install && echo -e "Kernel start: ${ks}\nKernel end: ${kf}"

and got this:

Version: Linux version 4.4.21-raspberrypi-v7-custom+ (root@pifukka) (gcc version 4.9.3 (Gentoo 4.9.3 p1.5, pie-0.6.4) ) #1 SMP Fri Sep 16 13:55:51 BST 2016
DT: y
DDT: y
270x: y
283x: n
Kernel start: Fri Sep 16 13:00:09 BST 2016
Kernel end: Fri Sep 16 14:00:00 BST 2016

You can add kernel=kernel-myconfig.img to config.txt to specify your own kernel name.

NOTE:  There is a hell of a lot of bloat in this, so if you know what you're doing, you could do a make menuconfig to trim the fat before you run make.

 

Using pump didn't work when compiling the kernel and failed very quickly.  So it's a 6 hour native compile for the default .config :(

It seems that there are just too many versions of the firmware floating about the tinterwebs.  So I managed to get this working by downloading the Jessie image from here, mounting the img file and copying the contents of /lib/firmware/brcm to the same location on the RPi.

Although the RPi3B has 802.11n, it will not use 5Ghz frequency band, only 2.4Ghz.

Once you have rebooted with the new kernel and firmware, hopefully you will now see the following in dmesg:

[ 7.270284] usbcore: registered new interface driver brcmfmac
[ 7.460455] cfg80211: World regulatory domain updated:
[ 7.460475] cfg80211: DFS Master region: unset
[ 7.460484] cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)
[ 7.460498] cfg80211: (2402000 KHz - 2472000 KHz @ 40000 KHz), (N/A, 2000 mBm), (N/A)
[ 7.460513] cfg80211: (2457000 KHz - 2482000 KHz @ 20000 KHz, 92000 KHz AUTO), (N/A, 2000 mBm), (N/A)
[ 7.460525] cfg80211: (2474000 KHz - 2494000 KHz @ 20000 KHz), (N/A, 2000 mBm), (N/A)
[ 7.460539] cfg80211: (5170000 KHz - 5250000 KHz @ 80000 KHz, 160000 KHz AUTO), (N/A, 2000 mBm), (N/A)
[ 7.460553] cfg80211: (5250000 KHz - 5330000 KHz @ 80000 KHz, 160000 KHz AUTO), (N/A, 2000 mBm), (0 s)
[ 7.460565] cfg80211: (5490000 KHz - 5730000 KHz @ 160000 KHz), (N/A, 2000 mBm), (0 s)
[ 7.460577] cfg80211: (5735000 KHz - 5835000 KHz @ 80000 KHz), (N/A, 2000 mBm), (N/A)
[ 7.460589] cfg80211: (57240000 KHz - 63720000 KHz @ 2160000 KHz), (N/A, 0 mBm), (N/A)
[ 8.339256] brcmfmac: brcmf_sdio_htclk: HT Avail timeout (1000000): clkctl 0x50
[ 9.349147] brcmfmac: brcmf_sdio_htclk: HT Avail timeout (1000000): clkctl 0x50
[ 10.359184] brcmfmac: brcmf_sdio_htclk: HT Avail timeout (1000000): clkctl 0x50

 


Systemdtop

OK.  So far we've got a bootable RPi using RC.  If you want to use systemd, we'll need to change a few things and also configure the daemons.

I added USE="systemd" to /etc/portage/make.conf

Don't forget to add init=/usr/lib/systemd/systemd to the line in cmdline.txt.

Yes systemd has it's pitfalls, but I've gotten used to it and actually quite like it <don't shoot me>

You'll then need to rebuild everything to use it.

emerge -uvND world

WIFI Networktop

Create the file:

vi /etc/systemd/network/wireless.network

And populate with content:

[Match]
Name=wlan0

[Network]
DHCP=ipv4
Domains=cdstealer.com

Also create this file:

vi /etc/wpa_supplicant/wpa_supplicant-wlan0.conf

And populate with content:

ctrl_interface=/var/run/wpa_supplicant


eapol_version=1


ap_scan=1


fast_reauth=1


network={
 ssid="<yourSSID"
 proto=WPA
 key_mgmt=WPA-PSK
 pairwise=CCMP TKIP
 group=CCMP TKIP WEP104 WEP40
 psk="yourSecretPassPhrase"
 priority=2
}

Then enable the services:

systemctl enable sshd
systemctl enable wpa_supplicant@wlan0
systemctl enable systemd-networkd

Localetop

As locales may vary, execute localectl list-locales and make a note of yours.  Mine is en_GB.utf8.  Then execute:

localectl set-locale LANG=en_GB.utf8

I also had to add LC_ALL="en_GB.utf8" to /etc/environment.

Hostnametop

hostnamectl set-hostname <hostname>

Keymaptop

localectl set-keymap uk

Execute localectl to confirm the settings:

# localectl status
 System Locale: LANG=en_GB.utf8
 VC Keymap: uk
 X11 Layout: gb
 X11 Model: pc105
 X11 Options: terminate:ctrl_alt_bksp

NTPtop

timedatectl set-ntp true

Drivers

Don't forget to install the driver package.

pump emerge raspberrypi-userland
pump emerge xorg-server

Should yield:

Total: 25 packages (25 new), Size of downloads: 11,256 KiB

Tweakstop

edit /boot/config.txt and add the following to the existing line dtoverlay=lirc-rpi, i2c_arm=on, dtoverlay=mmc,overclock_50=100

dtoverlay=lirc-rpi = loads the lirc modules for remotes.

i2c_arm=on = enabled i2c for the CPU.

dtoverlay=mmc,overclock_50=100 = this should speed up the SD access.  You may need to reduce the 100 value as I notice considerable file corruption.  Some forums have suggested a value of 83.

I also added the following to /etc/portage/make.conf

LINGUAS="en en_GB"
L10N="en en-GB"
VIDEO_CARDS="vc4"

Caveatstop

There are a few packages that are not compatible with distcc.  So if any of these give you butthurt when emerging,  Try emerging them individually.  Eg.  FEATURES="-distcc -distcc-pump" MAKEOPTS="-j4" emerge -av llvm.  Unfortunately that does mean slooooooooow compiles :(

Note:  When compiling anything without distcc, ensure you specify the MAKEOPTS as omitting this will crash the Pi.  The -j17 that was specified in /etc/portage/make.conf will be used which will be counter productive and slow down the builds until BOOM!

The common error that highlights this is at configure time:

Checking uname sysname type              : Traceback (most recent call last):

Affected packages:

Package (native compile time)
sys-libs/talloc (~3 minutes)
sys-devel/llvm (~200 minutes)
sys-libs/tdb (~7 minutes)
sys-libs/ntdb (~3 minutes)
sys-libs/tevent (~3 minutes)
media-video/ffmpeg (~22 minutes)
net-libs/socket_wrapper (~1 minute)
sys-libs/ldb (~4 minutes)
net-fs/samba (~44 minutes)


Now you need to decide what you want to do with it :)

KODItop

At this point, this should yield the following:

Total: 166 packages (164 new, 1 in new slot, 1 reinstall)

I have the following global USE flags set in /etc/portage/make.conf

USE="X systemd -bindist opengl xorg udev"

I also have the following local USE flags set in /etc/portage/package.use/package.use

# Kodi
>=sys-libs/tevent-0.9.28 python
>=sys-libs/ntdb-1.0-r1 python
>=dev-lang/python-2.7.10-r1:2.7 sqlite
>=sys-libs/tdb-1.3.8 python
media-tv/kodi -gles X alsa bluray css java samba usb opengl
media-libs/mesa gles2
media-libs/cogl gles2 opengl

I have the following packages in /etc/portage/package.keywords/package.keywords

# Kodi
=media-sound/dcadec-0.2.0 ~arm
=dev-libs/tinyxml-2.6.2-r2 ~arm
=app-eselect/eselect-java-0.2.0-r1 ~arm
#=media-tv/kodi-9999 **
=media-tv/kodi-16.0 **
=dev-java/icedtea-web-1.6.2 ~arm
=sys-apps/baselayout-java-0.1.0 ~arm
=virtual/jre-1.8.0-r1 ~arm
=dev-java/java-config-2.2.0-r3 ~arm
=virtual/jdk-1.8.0-r3 ~arm
=dev-java/icedtea-bin-3.1.0 ~arm
=dev-libs/crossguid-0_pre20150817 ~arm
=media-fonts/roboto-2.134 ~arm

I had to limit kodi to 16.0 as 9999 would not compile and repeatedly failed with EGLNative errors.  Each time failed costs 30 mins :(  A successful build takes ~90mins (not including deps).

MAMEtop

SDLMame yields:

Total: 49 packages (49 new)

Timecapsule on Linux

TimeMachine01_Logo1

TIME CAPSULE INSTALL & SETUP

Install Netatalk

# emerge -av netatalk
net-fs/netatalk-3.1.6::gentoo USE="(acl) avahi cracklib dbus pam samba shadow ssl tcpd utils -debug -kerberos -ldap -pgp -quota -static-libs -tracker" PYTHON_TARGETS="python2_7"

Configure Netatalk

Edit the file /etc/afp.conf:

vi /etc/afp.conf

Place the following contents. Edit the paths, usernames and IP range:

[Global]
 mimic model = TimeCapsule6,106
 log level = default:warn
 log file = /var/log/afpd.log
# either individual or CIDR
 hosts allow = 196.168.100.0/24

# I didn't require this option
#[Homes]
#basedir regex = /home

[TimeMachine]
 path = /mnt/data/timecapsule/
 valid users = me you someone
 time machine = yes
 appledouble = ea


# Nor did I require this.
#[Shared Media]
# path = /mnt/data/torrents/
# valid users = me you someone

Obviously, don't forget to create the mount point.

mkdir /mnt/data/timecapsule

Set the correct perms

chmod 775 /mnt/data/timecapsule

You will also need to change the group as this will currently be root:root

chown -R root.user /mnt/data/timecapsule

or

chgrp -R user /mnt/data/timecapsule

Create & Format the destination filesystem

Create the partition.
(I just used the whole 1Tb disk)

# fdisk /dev/sdb

Once the partition is defined, set the filesystem type of af.

Disk /dev/sdb: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb59eb59e

Device Boot Start End Sectors Size Id Type
/dev/sdb1 2048 1953525167 1953523120 931.5G af HFS / HFS+

Install the tool for formatting the filesystem.

Version 332.14_p1 at the time of writing.

emerge -av diskdev_cmds

Then format it

mkfs.hfsplus -v timemachine /dev/sdb1

Automount at boot time.  Add it to /etc/fstab

/dev/sdb1 /mnt/data/timecapsule hfsplus rw,noatime,user 0 1

Now mount it.

mount -a

Start the netatalk daemon. (I use systemd)

systemctl start netatalk

If all went to plan, the filesystem is mounted and the netatalk daemon running.  On the Mac, when you open Timemachine, you should automagically see your server.
Select it and enter the account details.  For security reasons, I created a new user on the server and set /sbin/nologin as the shell.  This way, the user has no access to the server and is not privileged to do anything.

Portage TMPFS

Portage TMPDIR on tmpfs

When emerging packages it is possible to build them in tmpfs (RAM) space instead of having build files pushed and pulled to Hard Disk Drive (HDD) or Solid State Drive (SSD) space. Building in tmpfs both speeds up emerge times and reduces HDD/SSD wearing. For system's containing SSDs, it is generally a good idea to have Portage compile using tmpfs (RAM) instead burning up precious SSD write cycles (especially on something like compiling software).

fstab Configuration

Mount Portage's TMPDIR to tmpfs by adding the following to the system's /etc/fstab config file:

FILE /etc/fstab tmpfs fstab example
tmpfs		/var/tmp/portage		tmpfs	uid=portage,gid=portage,mode=775,size=2048M,noatime	0 0

Adjust the size parameter /etc/fstab to the desired amount of RAM. Systems with large amounts of RAM can increase the number quite significantly.

After /etc/fstab has been modified, mount Portage's TMPDIR to RAM by running the mount command followed by the directory location outline in fstab:

root #mount /var/tmp/portage

Considering tmpfs' Size

The system's tmpfs space should be large enough to handle the largest packages to be compiled on the system. If the tmpfs space were to ever become completely full then the emerge will fail. Most packages do not need more than 1 GB of tmpfs space their compiles, but there are few very large packages. If you have a lot of RAM, setting Be careful to include enough tmpfs space when installing the following packages:

app-office/openoffice: 10GBs or so.

www-client/chromium: More than 2GBs.

sys-devel/gcc: More than 4 GiB.

Per-Package Choices at Compile Time

Portage can be configured to build large packages outside of the tmpfs space on a per-package basis.

Create a file to tell Portage where to place the temporary files directory:

FILE /etc/portage/env/notmpfs.conf
PORTAGE_TMPDIR="/var/tmp/notmpfs"

Create a separate temporary file directory outside of the tmpfs mount location:

mkdir /var/tmp/notmpfs && chown portage:portage /var/tmp/notmpfs && chmod 775 /var/tmp/notmpfs

Create a special Portage file called package.env in /etc/portage and list all the packages that are too large to be compiled using tmpfs:

FILE /etc/portage/package.env
app-office/libreoffice notmpfs.conf
mail-client/mozilla-thunderbird notmpfs.conf
www-client/chromium notmpfs.conf