How to install Arch Linux on a USB key from an existing Linux (Debian)


We are going to install Arch Linux distro in an USB storage device from an existing GNU/Linux system (Debian).

This is not about creating a live USB but a standard distro on an USB key.


We are going to install Arch Linux in a two step process. First we create an Arch Linux bootstrap in our Debian host system.
Then we will chroot into it, and after that we will install Arch Linux in the USB key.



Install Arch Linux from an existing Debian system on an USB key


Install from existing Linux:
https://wiki.archlinux.org/index.php/Install_from_existing_Linux


First we plug the USB device, and check devices and partitions with lsblk command:
$ lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT
sda
├─sda1 ext4 system cbdfff17-0865-448e-b7c1-04a50d168439 /
├─sda2 swap ee7134ec-a542-4c42-8b2e-8e40d3f59980 [SWAP]
└─sda3 ext4 home 9fbcbeb8-8723-43e1-8d08-340af9e14b8b /home
sdb
└─sdb1
sr0


I am going to install it in /deb/sdb device.

I partition the device and create a bootable only partition.
$ sudo fdisk -l /dev/sdb
Disk /dev/sdb: 15 GiB, 16131293184 bytes, 31506432 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: 0x04030201

Device Boot Start End Sectors Size Id Type
/dev/sdb1 * 2048 31506431 31504384 15G 83 Linux



Format the partition with ext4 without journaling to minimize writes to USB key.
$ sudo mkfs.ext4 -O "^has_journal" -L 'ArchUSB' /dev/sdb1



Downloading Arch Linux bootstrap


Architecture of my system is x86_64.
$ uname -m
x86_64

I get bootstrap ISO from a mirror listed in this page:
https://www.archlinux.org/download/

Get bootstrap:
$ curl -O http://sunsite.rediris.es/mirror/archlinux/iso/2016.11.01/archlinux-bootstrap-2016.11.01-x86_64.tar.gz

I download signature to same directory:
$ curl -O http://sunsite.rediris.es/mirror/archlinux/iso/2016.11.01/archlinux-bootstrap-2016.11.01-x86_64.tar.gz.sig

And verify it:
$ gpg --keyserver-options auto-key-retrieve --verify archlinux-bootstrap-2016.11.01-x86_64.tar.gz.sig


Directory in host system to extract the bootstrap:
$ mkdir arch_chroot

Extract the tarball:
$ tar xzf archlinux-bootstrap-2016.11.01-x86_64.tar.gz -C arch_chroot


Edit arch_chroot/root.x86_64/etc/pacman.d/mirrorlist and uncomment the mirror you are going to use:
(Uncommenting several mirrors is a good idea)
E.g:
Server = http://sunsite.rediris.es/mirror/archlinux/$repo/os/$arch


Enter the chroot:
https://wiki.archlinux.org/index.php/Change_root

$ sudo mount --bind arch_chroot/root.x86_64 arch_chroot/root.x86_64 # This will provide / in chroot env.
$ cd arch_chroot/root.x86_64/
$ sudo cp /etc/resolv.conf etc
$ sudo mount -t proc /proc proc
$ sudo mount --rbind /sys sys
$ sudo mount --rbind /dev dev
$ sudo mount --rbind /run run # (assuming /run exists on the system)
$ sudo chroot . /bin/bash
[root@ /]#

We are inside the chroot jail now.



Install needed packages in Arch Linux bootstrap


First we are going to initialize package manager pacman:

https://wiki.archlinux.org/index.php/Pacman

Initialize pacman keyring
https://wiki.archlinux.org/index.php/Pacman-key#Initializing_the_keyring

# pacman-key --init
System will need entropy so open another console(in the host machine) and run $ ls -Ra / several times.

# pacman-key --populate archlinux


https://wiki.archlinux.org/index.php/Mirrors#Enabling_a_specific_mirror
synchronize package databases: (if one server does not work edit more in etc/pacman.mirrorlist)
# pacman -Syyu
:: Synchronizing package databases...


Install base packages:
# pacman -S base



Install basic packages in Arch Linux USB key


General installation guide:
https://wiki.archlinux.org/index.php/Installation_guide


Mount the USB device in /mnt directory:
# mount /dev/sdb1 /mnt

Install base packages:
# pacstrap /mnt base

Generate fstab (I use -U to define by UUID):
# genfstab -U /mnt >> /mnt/etc/fstab
Check /mnt/etc/fstab has correct data.

Change root into the new system:
# arch-chroot /mnt

Set Time Zone: (change to your Region and City /usr/share/zoneinfo/Region/City )
# ln -s /usr/share/zoneinfo/Europe/Madrid /etc/localtime

Run hwclock(8) to generate /etc/adjtime:
# hwclock --systohc


Locale

Uncomment en_US.UTF-8 UTF-8 and other needed localizations in /etc/locale.gen, and generate them with:
# locale-gen

Set the LANG variable in locale.conf(5) accordingly, for example:

/etc/locale.conf

LANG=en_US.UTF-8


It didn't exist so I create it
# echo "LANG=en_US.UTF-8" > /etc/locale.conf


Keyboard

If you set the keyboard layout, make the changes persistent in vconsole.conf(5):

/etc/vconsole.conf

E.g: KEYMAP=de-latin1

To list available layouts:
# ls /usr/share/kbd/keymaps/**/*.map.gz

I choose es for Spanish keyboard:
# echo "KEYMAP=es" > /etc/vconsole.conf


Hostname

Create the hostname(5) file:

/etc/hostname

E.g: I name my system archUSB:
# echo "archUSB" > /etc/hostname


Consider adding a matching entry to hosts(5):

/etc/hosts

127.0.0.1	localhost.localdomain	localhost
::1		localhost.localdomain	localhost
127.0.1.1	archUSB.localdomain	archUSB



Root password

Set the root password:
# passwd



Network configuration (inside chroot jail)


Configure the network for the newly installed environment
https://wiki.archlinux.org/index.php/Network_configuration

For Wireless configuration, install the iw, wpa_supplicant, and dialog packages, as well as needed firmware packages.

I install network manager:
# pacman -S networkmanager

and dhclient:
# pacman -S dhclient



Initramfs


In this case we will need to create a new initramfs.


Modify the mkinitcpio.conf(5) file:

I edit and uncomment this in /etc/mkinitcpio.conf so block appears:
HOOKS="base udev block filesystems"


To avoid crc32c error when loading modules:
MODULES="crc32 libcrc32c crc32c_generic crc32c-intel crc32-pclmul"


Recreate the initramfs image:
# mkinitcpio -p linux



BOOTLOADER


Bootloader (I select GRUB for my non-UEFY system):
https://wiki.archlinux.org/index.php/GRUB#BIOS_systems

Install grub instead of grub-legacy:
# pacman -S grub

# grub-install --target=i386-pc /dev/sdb
or
# grub-install --target=i386-pc --recheck /dev/sdb
Installing for i386-pc platform.
Installation finished. No error reported.


# grub-mkconfig -o /boot/grub/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-linux
Found initrd image(s) in /boot: initramfs-linux.img
Found fallback initrd image(s) in /boot: initramfs-linux-fallback.img
done



Exit last chroot using exit:
# exit

Now manually unmount all partitions (if someone busy find the cause with fuser)
# umount -R /mnt

exit second chroot
# exit

Now we are again in the host system:
$ cd ..
$ sudo umount -R root.x86_64


Now you can boot in your new Arch Linux USB key or test it in an emulator.

To test the Arch Linux USB key with virtualbox:
VirtualBox: add a physical hard disk to your virtual machine in Debian



Network setup (in the working Arch Linux USB key)


https://wiki.archlinux.org/index.php/Network_configuration

I am going to configure a dynamic address on a wired NIC.
Choose one method to configure your network because several at once could conflict.



Check current state of NIC devices

E.g: Display all network devices:
$ ip link show
1: lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 70:5a:b6:43:58:8c brd ff:ff:ff:ff:ff:ff



E.g: Show addresses:
$ ip address
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 70:5a:b6:43:58:8c brd ff:ff:ff:ff:ff:ff
inet 192.168.0.105/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::725a:b6ff:fe43:588c/64 scope link
valid_lft forever preferred_lft forever




Configure the network using dhclient

For this to work you need to have already installed dhclient in the bootstrap process:
# packman -S dhclient

Enable the network device:
# ip link set enp0s3 up

Ask for a dynamic address:
# dhclient enp0s3

Check it worked:
# ip address show enp0s3

# ping www.google.com



How to configure a netctl profile and start it

Configure network using a profile (E.g dhcp profile)

https://wiki.archlinux.org/index.php/Netctl

Copy an example profile:
# cp /etc/netctl/examples/ethernet-dhcp /etc/netctl/my-ethernet-dhcp-profile

Edit it an change to match our interface name:
# nano /etc/netctl/my-ethernet-dhcp-profile
change Interface=eth0 into Interface=enp0s3

Be sure the device is down when starting the profile.
# ip link set enp0s3 down

Start the profile:
# netctl start my-ethernet-dhcp-profile

Check it works:
# ping www.google.com

Next time you boot the system it will launch automatically.



How to configure SSH server


If we want to connect remotelly to the Arch Linux system we could use sshd server.

https://wiki.archlinux.org/index.php/Secure_Shell

Install ssh server
# pacman openssh

Edit config file for ssh server:
# nano /etc/ssh/ssdh_config

If we want to login as root (although it is insecure)
PermitRootLogin yes

Launch the server
# systemctl edit sshd.socket

https://wiki.archlinux.org/index.php/Start
# systemctl start sshd.socket

if it fails, to watch the logs:
# journalctl /usr/bin/sshd


From remote machine:
$ ssh -l root address_of_your_arch_linux_machine



REFERENCE


Arch Linux distro - Introduction

Improving_performance (Arch Linux wiki)