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:

First we plug the USB device, and check devices and partitions with lsblk command:
$ lsblk -f
├─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

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

I get bootstrap ISO from a mirror listed in this page:

Get bootstrap:
$ curl -O

I download signature to same directory:
$ curl -O

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)
Server =$repo/os/$arch

Enter the chroot:

$ 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:

Initialize pacman 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
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:

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


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:



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


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


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


Create the hostname(5) file:


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

Consider adding a matching entry to hosts(5):

/etc/hosts	localhost.localdomain	localhost
::1		localhost.localdomain	localhost	archUSB.localdomain	archUSB

Root password

Set the root password:
# passwd

Network configuration (inside chroot jail)

Configure the network for the newly installed environment

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


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 (I select GRUB for my non-UEFY system):

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

# grub-install --target=i386-pc /dev/sdb
# 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

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)

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 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 brd 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

How to configure a netctl profile and start it

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

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

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.

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
# 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


Arch Linux distro - Introduction

Improving_performance (Arch Linux wiki)