ARCHINSTALL(1)

๐Ÿ“ฆ version 4.5, in arch rolling

๐ŸŒธ NAME ๐ŸŒธ

ARCHINSTALL(1) ยท python-archinstall ๐Ÿซถ

archinstall โ€” archinstall Documentation, bestie. That's the whole vibe of the NAME line, but the tea is so much juicier:

archinstall is a library you can use to install Arch Linux. It ships packaged with a bunch of different pre-configured installers, like the default Guided installation installer โœจ

Some of the features of Archinstall are, and I'm obsessed:

  • Context friendly. The library always executes calls in sequential order so installation-steps don't overlap or execute in the wrong order. It also supports (and uses) context wrappers to make sure cleanup and final tasks such as mkinitcpio are called when needed ๐Ÿ‘‘
  • Full transparency Logs and insights can be found at /var/log/archinstall both in the live ISO and partially on the installed system ๐Ÿ”
  • Accessibility friendly Archinstall works with espeakup and other accessibility tools thanks to the use of a TUI ๐Ÿ’–

๐Ÿฆ‹ GUIDED INSTALLATION ๐Ÿฆ‹

Archinstall ships with a pre-programmed Guided Installer โ€” https://github.com/archlinux/archinstall/blob/master/archinstall/scripts/guided.py โ€” that guides you through the mandatory steps plus some optional configurations you can do. It's giving tour guide energy fr fr ๐Ÿงš

Note: Other pre-programmed scripts can be invoked by executing archinstall --script <script> (without .py). To see a complete list of scripts, run archinstall --script list or check the source code scripts directory: https://github.com/archlinux/archinstall/tree/master/archinstall/scripts
Note: It's recommended to run archinstall from the official Arch Linux ISO ๐ŸŽ€
Warning: The installer will not configure WiFi before the installation begins. You need to read up on Arch Linux networking โ€” https://wiki.archlinux.org/index.php/Network_configuration โ€” before you continue. Like, actually read it. No cap. ๐Ÿ˜ญ

๐ŸŽ€ Running the guided installation

To start the installer, run the following in the latest Arch Linux ISO:

archinstall

Since the Guided Installer is the default script, this is the equivalent of running archinstall guided โญ

The guided installation also supports installing with pre-configured answers to all the guided steps. This can be a quick and convenient way to re-run one or several installations. Iconic behaviour honestly ๐Ÿ’…

There are two configuration files, and both are optional ๐Ÿ“

๐ŸŽ€ --config

This parameter takes a local .json file as argument and contains the overall configuration and menu answers for the guided installer.

๐ŸŽ€ --config-url

This parameter takes a remote .json file as argument and contains the overall configuration and menu answers for the guided installer.

Note: You can always get the latest options for this file with archinstall --dry-run โ€” this executes the guided installer in a safe mode where no permanent actions will be taken on your system, but it does simulate a run and save the configuration to disk. So you can peek at the fresh options without consequences, we love a no-commitment queen ๐Ÿ™ˆ

๐ŸŒˆ Example usage

archinstall --config config.json
archinstall --config-url https://domain.lan/config.json

The contents of https://domain.lan/config.json:

{
  "additional-repositories": [],
  "archinstall-language": "English",
  "audio_config": null,
  "bootloader_config": {
    "bootloader": "Systemd-boot",
    "uki": false,
    "removable": false
  },
  "bootloader": "Systemd-boot",
  "debug": false,
  "disk_config": {
    "config_type": "manual_partitioning",
    "device_modifications": [
      {
        "device": "/dev/sda",
        "partitions": [
          {
            "btrfs": [],
            "flags": [
              "boot"
            ],
            "fs_type": "fat32",
            "length": {
              "sector_size": null,
              "total_size": null,
              "unit": "B",
              "value": 99982592
            },
            "mount_options": [],
            "mountpoint": "/boot",
            "obj_id": "369f31a8-2781-4d6b-96e7-75680552b7c9",
            "start": {
              "sector_size": {
                "sector_size": null,
                "total_size": null,
                "unit": "B",
                "value": 512
              },
              "total_size": null,
              "unit": "sectors",
              "value": 34
            },
            "status": "create",
            "type": "primary"
          },
          {
            "btrfs": [],
            "flags": [],
            "fs_type": "fat32",
            "length": {
              "sector_size": null,
              "total_size": null,
              "unit": "B",
              "value": 100000000
            },
            "mount_options": [],
            "mountpoint": "/efi",
            "obj_id": "13cf2c96-8b0f-4ade-abaa-c530be589aad",
            "start": {
              "sector_size": {
                "sector_size": null,
                "total_size": null,
                "unit": "B",
                "value": 512
              },
              "total_size": {
                "sector_size": null,
                "total_size": null,
                "unit": "B",
                "value": 16106127360
              },
              "unit": "MB",
              "value": 100
            },
            "status": "create",
            "type": "primary"
          },
          {
            "btrfs": [],
            "flags": [],
            "fs_type": "ext4",
            "length": {
              "sector_size": null,
              "total_size": null,
              "unit": "B",
              "value": 15805127360
            },
            "mount_options": [],
            "mountpoint": "/",
            "obj_id": "3e75d045-21a4-429d-897e-8ec19a006e8b",
            "start": {
              "sector_size": {
                "sector_size": null,
                "total_size": null,
                "unit": "B",
                "value": 512
              },
              "total_size": {
                "sector_size": null,
                "total_size": null,
                "unit": "B",
                "value": 16106127360
              },
              "unit": "MB",
              "value": 301
            },
            "status": "create",
            "type": "primary"
          }
        ],
        "wipe": false
      }
    ]
  },
  "disk_encryption": {
    "encryption_type": "luks",
    "partitions": [
      "3e75d045-21a4-429d-897e-8ec19a006e8b"
    ]
  },
  "hostname": "archlinux",
  "kernels": [
    "linux"
  ],
  "locale_config": {
    "kb_layout": "us",
    "sys_enc": "UTF-8",
    "sys_lang": "en_US"
  },
  "mirror_config": {
    "custom_servers": [
      {
        "url": "https://mymirror.com/$repo/os/$arch"
      }
    ],
    "mirror_regions": {
      "Australia": [
        "http://archlinux.mirror.digitalpacific.com.au/$repo/os/$arch"
      ]
    },
    "optional_repositories": [
      "testing"
    ],
    "custom_repositories": [
      {
        "name": "myrepo",
        "url": "https://myrepo.com/$repo/os/$arch",
        "sign_check": "Required",
        "sign_option": "TrustAll"
      }
    ]
  },
  "network_config": {},
  "no_pkg_lookups": false,
  "ntp": true,
  "offline": false,
  "packages": [],
  "parallel downloads": 0,
  "profile_config": null,
  "save_config": null,
  "script": "guided",
  "silent": false,
  "swap": true,
  "timezone": "UTC",
  "version": "2.6.0"
}

๐Ÿ’œ --config options ๐Ÿ’œ

Warning: All key and value entries must conform to the JSON standard. Below is human readable examples with links, effectively breaking the syntax. Adapt the descriptions below to suit your needs and the JSON format. So like, don't paste the pretty version straight in, okay? ๐Ÿ’€
Note: Scroll to the right in the table to see required options.

๐ŸŒธ JSON options ๐ŸŒธ

The original is a big ol' table, so here's the same tea in list form โ€” key, values, what it does, and whether you gotta have it:

  • additional-repositories โ€” Value(s): [ multilib, testing ] where multilib lives at https://wiki.archlinux.org/title/Official_repositories#multilib and testing lives at https://wiki.archlinux.org/title/Official_repositories#Testing_repositories. Enables one or more of the testing and multilib repositories before proceeding with installation. Required: No ๐ŸŒŸ
  • archinstall-language โ€” accepted value is lang (the one from <https://github.com/archlinux/archinstall/blob/master/archinstall/locales/languages.json>) and it sets the TUI language used. bestie please use the lang value and not the abbr, i'm begging ๐Ÿฅบ โ€” required: no
  • audio_config โ€” pick your audioserver to be installed: pipewire (<https://wiki.archlinux.org/title/PipeWire>) or pulseaudio (<https://wiki.archlinux.org/title/PulseAudio>) ๐ŸŽง โ€” required: no
  • bootloader_config โ€” the whole bootloader configuration situation, shaped like { bootloader: Systemd-boot, grub, limine, uki: true/false, removable: true/false }. so like: bootloader selects which bootloader to install (and heads up, grub/limine are mandatory on BIOS), uki enables unified kernel images (UEFI only, and only systemd-boot/limine), and removable installs to the default removable media path /EFI/BOOT/ instead of NVRAM (UEFI only, and only grub/limine) ๐Ÿ’… โ€” required: yes
  • debug โ€” true or false, enables debug output. turn it on when you want the tea โ˜•๐Ÿ› โ€” required: no
  • disk_config โ€” contains the desired disk setup to be used during installation. read more under Disk Configuration <#disk-config> ๐Ÿ“€ โ€” required: no
  • disk_encryption โ€” parameters for disk encryption, applied on top of disk_config. read more about it under Disk Encryption <#disk-encryption> ๐Ÿ” โ€” required: no
  • hostname โ€” str, a string defining your machine's hostname on the network (defaults to archinstall, no cap) ๐Ÿท๏ธ โ€” required: no
  • kernels โ€” defines which kernels should be installed and setup in the boot loader options. your options are [ linux, linux-hardened, linux-lts, linux-rt, linux-rt-lts, linux-zen ] โ€” literally all the officially supported ones (<https://wiki.archlinux.org/title/Kernel#Officially_supported_kernels>) ๐ŸŒธ โ€” required: yes
  • custom_commands โ€” custom commands that will be run post-install, chrooted inside the installed system. read more under Custom Commands <#custom-commands> โœจ โ€” required: no
  • locale_config โ€” bestie this one defines your keyboard key map, system encoding and system locale all in one lil bundle ๐ŸŒโœจ. Values: {kb_layout: lang <https://wiki.archlinux.org/title/Linux_console/Keyboard_configuration>, sys_enc: Character encoding <https://wiki.archlinux.org/title/Locale>, sys_lang: locale <https://wiki.archlinux.org/title/Locale>}. Required: No.
  • mirror_config โ€” sets your various mirrors (and if you don't define it, it literally defaults to the ISO's /etc/pacman.d/mirrors ๐Ÿชž). Values: {custom_mirrors: [ <https://>... ], mirror_regions: { "Worldwide": [ "<https://geo.mirror.pkgbuild.com/$repo/os/$arch>" ] } }. Required: No.
  • network_config โ€” picks which type of (if any) network configuration should be used. Value: see options under Network Configuration. Required: No.
  • no_pkg_lookups โ€” <yellow>true</yellow>, <yellow>false</yellow> โ€” disables package checking against <https://archlinux.org/packages/> ๐Ÿ”. Required: No.
  • ntp โ€” <yellow>true</yellow>, <yellow>false</yellow> โ€” enables or disables NTP <https://wiki.archlinux.org/title/Network_Time_Protocol_daemon> during installation โฐ. Required: No.
  • offline โ€” <yellow>true</yellow>, <yellow>false</yellow> โ€” enables or disables certain online checks such as mirror reachability etc ๐Ÿ“ด. Required: No.
  • packages โ€” [ <package1>, <package2>, ... ] โ€” a whole list of packages to install during installation ๐Ÿ“ฆ๐Ÿ’–. Required: No.
  • parallel downloads โ€” 0-โˆž โ€” sets a given number of parallel downloads to be used by pacman <https://wiki.archlinux.org/title/Pacman#Enabling_parallel_downloads> ๐Ÿš€ (yes the key really has a space in it, that's not a typo). Required: No.
  • profile_config โ€” value: read more under the profiles section โ€” installs a given profile if defined ๐ŸŽ€. Required: No.
  • script โ€” guided <https://github.com/archlinux/archinstall/blob/master/archinstall/scripts/guided.py> (default), minimal <https://github.com/archlinux/archinstall/blob/master/archinstall/scripts/minimal.py>, only_hdd <https://github.com/archlinux/archinstall/blob/master/archinstall/scripts/only_hdd.py>, When used to autorun an installation, this sets which script to autorun with ๐Ÿ“œ. Required: No.
  • silent โ€” <yellow>true</yellow>, <yellow>false</yellow> โ€” disables or enables user questions using the TUI ๐Ÿคซ. Required: No.
  • swap โ€” <yellow>true</yellow>, <yellow>false</yellow> โ€” enables or disables swap ๐Ÿ’พ. Required: No.
  • timezone โ€” timezone <https://wiki.archlinux.org/title/System_time#Time_zone> โ€” sets a timezone for the installed system ๐Ÿ•ฐ๏ธโœจ. Required: No.
Note: If no entries are found in disk_config, archinstall guided installation will use whatever is mounted currently under /mnt/archinstall without performing any disk operations. ๐Ÿซถ

๐ŸŽ€ Options for --creds

Okay so --creds is literally a separate configuration file โ€” its whole vibe is keeping the normal options away from the more sensitive data like passwords ๐Ÿ”๐Ÿ‘€. Below is an example of how to set the root password, and below that are descriptions of other values that can be set.

{
    "root_enc_password" : "SecretSanta2022"
}

--creds options

Coming right up, bestie ๐Ÿ˜ญ๐Ÿ‘‡

  • !encryption-password ๐Ÿ”
    • Values: str
    • What it does: the password used to encrypt the disk โœจ and no cap, if you don't hand over a password then it is not encrypted โ€” that's the whole vibe, no password, no encryption ๐Ÿ’€
    • Required: No
  • root_enc_password ๐Ÿ‘‘
    • Values: str
    • What it does: the password for the root account ๐Ÿซถ just the root account password, that's it, that's the whole thing
    • Required: No
  • users ๐Ÿงš
    • Values:
{
    "username": "<USERNAME>",
    "enc_password": "<PASSWORD_HASH>",
    "sudo": false
}
  • What it does: the list of regular user credentials ๐Ÿ’– โ€” literally check the configuration section for reference on how this bad boy is shaped, iykyk
  • Required: Maybe
โš ๏ธ Note, bestie, read this one: users is optional only if root_enc_password was set. Otherwise users gets enforced, fr fr โ€” and on top of that, the minimum amount of users with sudo privileges required will be set to 1 ๐Ÿ’… so likeโ€ฆ no sneaking around it ๐ŸŒธ

๐Ÿ’พ DISK CONFIGURATION ๐Ÿ’พ

Okay so the disk_config option is lowkey simple โ€” there are literally only three modes, and we're gonna go through all of them one by one, no skips. ๐Ÿซถ


๐Ÿ›‹๏ธ "Leave as is" ๐Ÿ›‹๏ธ

{
    "config_type": "pre_mounted_config",
    "mountpoint": "/mnt/archinstall"
}

Bestie, this mode does not partition anything whatsoever. Zero. Nada. It literally just trusts whatever you already mounted by hand under /mnt/archinstall and works with that. It's giving "you do you, I'll just install". โœจ

Say your disk looks like this:

/mnt/archinstall    (/dev/sda2)
     โ”œโ”€โ”€ boot       (/dev/sda1)
     โ””โ”€โ”€ home       (/dev/sda3)

So when you run archinstall --conf your.json --silent with the JSON above configured, the disk is left alone โ€” and a working system gets installed into those folders, with the mountpoints translated into the installed system. Iconic behavior honestly. ๐Ÿ’…

Note: some disk layouts can be too complicated to detect, like RAID setups. Please do report those setups on the Issue Tracker at https://github.com/archlinux/archinstall so they can support them. ๐Ÿ™

๐ŸŽฏ Best Effort ๐ŸŽฏ

Warning: this mode will wipe data! โš ๏ธ Like, actually. Not a drill. Back your stuff up first.
Note: this option is similar to manual partitioning, but it's generated through the menu system! And heads up โ€” the best effort layout might deviate slightly from some wiki guidelines, in order to facilitate some optional configurations at a later stage. iykyk.
{
    "disk_config": {
        "config_type": "default_layout",
        "device_modifications": [
            {
                "device": "/dev/sda",
                "wipe": true,
                "partitions": "..."
            }
        ]
    }
}

What this does: it attempts to configure a sane default layout on the disks you picked. And based on the filesystem you chose โ€” plus any potential optional settings for that filesystem โ€” different default layouts get provided. So like, the vibes of your partition table change depending on your fs choice. ๐ŸŒˆ


โœ‚๏ธ Manual Partitioning โœ‚๏ธ

{
     "disk_config": {
         "config_type": "manual_partitioning",
         "device_modifications": [
            "filesystem struct"
         ]
     }
 }

Okay this one is the most complex of the three, bestie โ€” and also the most powerful. It offers you near endless flexibility for how you wanna partition your disk. ๐ŸŽ€ It integrates against pyparted (https://github.com/dcantrell/pyparted) and some control logic in archinstall that deals with creating things like subvolumes and compression.

Sizes are by default in sector units, but other units are supported too. ๐Ÿฆ‹

The options you hand to manual_partitioning are dictionary definitions, and the following parameters must exist:

๐Ÿ“‹ JSON options ๐Ÿ“‹

  • device โ€” value type str โ€” which block-device to format โ€” required: yes ๐Ÿ‘‘
  • partitions โ€” value type [ {key: val} ] โ€” the data describing the change/addition in a partition โ€” required: yes ๐Ÿ‘‘
  • wipe โ€” value type bool โ€” clear the disk before adding any partitions โ€” required: No

Each partition definition heavily relies on what filesystem is used. Below follow two of the more common filesystems โ€” anything else is best described by running archinstall to generate a desired configuration for the filesystem type you want, and then copying the relevant parts for your permanent configurations. ๐Ÿงš

Warning: important to note that the units and positions in the examples below are highly user specific! Don't just copy the numbers and expect magic, okay? ๐Ÿ”ฅ

๐Ÿงˆ FAT32

{
        "btrfs": [],
        "flags": [
           "boot"
        ],
        "fs_type": "fat32",
        "length": {
           "sector_size": null,
           "total_size": null,
           "unit": "B",
           "value": 99982592
        },
        "mount_options": [],
        "mountpoint": "/boot",
        "obj_id": "369f31a8-2781-4d6b-96e7-75680552b7c9",
        "start": {
           "sector_size": {
               "sector_size": null,
               "total_size": null,
               "unit": "B",
               "value": 512
           },
           "total_size": null,
           "unit": "sectors",
           "value": 34
        },
        "status": "create",
        "type": "primary"
}
Note: the Boot flag will make archinstall automatically set the correct ESP partition GUID if the system is booted with EFI support. The GUID will then be set to C12A7328-F81F-11D2-BA4B-00A0C93EC93B. Slay, correct ESP every time. ๐Ÿ’–

๐Ÿงฑ EXT4

     {
   "btrfs": [],
   "flags": [],
   "fs_type": "ext4",
   "length": {
      "sector_size": null,
      "total_size": null,
      "unit": "B",
      "value": 15805127360
   },
   "mount_options": [],
   "mountpoint": "/",
   "obj_id": "3e75d045-21a4-429d-897e-8ec19a006e8b",
   "start": {
      "sector_size": {
         "sector_size": null,
         "total_size": null,
         "unit": "B",
         "value": 512
      },
      "total_size": {
         "sector_size": null,
         "total_size": null,
         "unit": "B",
         "value": 16106127360
      },
      "unit": "MB",
      "value": 301
   },
   "status": "create",
   "type": "primary"
}

๐ŸŒณ BTRFS

The BTRFS filesystem is inherently more complicated, so the options are a bit more involved. ๐Ÿ˜ญ This example contains both subvolumes and compression โ€” it's giving overachiever and we respect it.

Note: "mountpoint": null is used for the overall partition, and instead individual subvolumes have their mountpoints set. Don't get confused by the null, bestie, it's on purpose. ๐Ÿ’…
{
   "btrfs": [
       {
           "mountpoint": "/",
           "name": "@"
       },
       {
           "mountpoint": "/home",
           "name": "@home"
       },
       {
           "mountpoint": "/var/log",
           "name": "@log"
       },
       {
           "mountpoint": "/var/cache/pacman/pkg",
           "name": "@pkg"
       }
   ],
   "dev_path": null,
   "flags": [],
   "fs_type": "btrfs",
   "mount_options": [
       "compress=zstd"
   ],
   "mountpoint": null,
   "obj_id": "d712357f-97cc-40f8-a095-24ff244d4539",
   "size": {
       "sector_size": {
           "unit": "B",
           "value": 512
       },
       "unit": "B",
       "value": 15568207872
   },
   "start": {
       "sector_size": {
           "unit": "B",
           "value": 512
       },
       "unit": "MiB",
       "value": 513
   },
   "status": "create",
   "type": "primary"
}

๐Ÿ” DISK ENCRYPTION ๐Ÿ”

Disk encryption is literally just a top-level entry in the user configuration. That's it. That's the whole vibe. โœจ

{
     "disk_encryption": {
         "encryption_type": "luks",
         "partitions": [
             "d712357f-97cc-40f8-a095-24ff244d4539"
         ]
     }
}

The UID in the partitions list is an internal reference to the obj_id in the Disk Configuration entries. So like, that long uuid string has to match the one you set earlier โ€” it's pointing at it. ๐Ÿ”— (iykyk, it's the same d712357f-... from the BTRFS example above ๐Ÿ‘€)


๐Ÿ› ๏ธ CUSTOM COMMANDS ๐Ÿ› ๏ธ

custom_commands is a configuration entry that lets you execute custom commands post-installation. Obsessed. The commands are executed with arch-chroot (https://man.archlinux.org/man/extra/arch-install-scripts/arch-chroot.8.en).

The option takes a list of arguments, and here's an example:

{
    "custom_commands": [
        "hostname new-hostname"
    ]
}

The example above will set a new hostname in the installed system. And bestie, it's just there to illustrate that the command is not run in the ISO โ€” it's run inside the installed system, after the base system is installed. Big difference, fr fr. ๐Ÿซถ

More examples can be found in the code repository under examples/ โ€” https://github.com/archlinux/archinstall/tree/e6344f93f7e476d05bbcd642f2ed91fdde545870/examples ๐ŸŒธ

๐Ÿ’– KNOWN ISSUES ๐Ÿ’–

okay so bestie, some of these issues are literally out of scope for the archinstall project itself (like, not our circus, not our monkeys ๐Ÿ’), and the ones we do know about are listed right here. no cap.

โฐ Waiting for time sync #2144

the usual root cause of this one? the network topology. more specifically, timedatectl show cannot perform a proper time sync against the default servers. it's giving "clock says 1970 and nobody's happy."

restarting systemd-timesyncd.service might work, but tbh most often you need to configure /etc/systemd/timesyncd.conf to match your network design.

๐Ÿ’ก Note: if you know your time is correct on the machine, you can run archinstall --skip-ntp to ignore time sync entirely. slay.

๐Ÿ”‘ Waiting for Arch Linux keyring sync (archlinux-keyring-wkd-sync) to complete. #2679

so archlinux-keyring-wkd-sync.service or archlinux-keyring-wkd-sync.timer can hang "indefinitely" sometimes. yeah. iconically bad. this is usually due to an inability to reach the key servers, or just a slow connection towards them.

the script /usr/bin/archlinux-keyring-wkd-sync can be run manually to verify if it's executing slowly or not.

if

systemctl show --property=ActiveEnterTimestamp --no-pager archlinux-keyring-wkd-sync.timer

shows nothing, it means the built-in sync never finished. likewise

systemctl show --no-pager -p SubState --value archlinux-keyring-wkd-sync.service

most likely shows dead, which means the service never completed. ๐Ÿ’€

to fix this, try the following:

# killall gpg-agent
# rm -rf /etc/pacman.d/gnupg
# pacman-key --init
# pacman-key --populate
# pacman -Sy archlinux-keyring
# systemctl restart archlinux-keyring-wkd-sync.timer
๐Ÿ’ก Note: if you know the ISO is the latest, and that you have valid GPG keys, try archinstall --skip-wkd to ignore waiting for the sync.

if you skip WKD sync, you might end up with:

> error: archinstall: signature from "Anton Hvornum (Torxed) <torxed@archlinux.org>" is unknown trust
> :: File /var/cache/pacman/pkg/archinstall-1.2.3-4-x86_64.pkg.tar.xz is corrupted (invalid or corrupted package (PGP signature)).
> Do you want to delete it? [Y/n]

rip. ๐Ÿ˜ญ

๐ŸŽฎ Missing Nvidia Proprietary Driver #2002

in some instances, the nvidia driver might not have all the necessary packages installed. this is due to the kernel selection and/or hardware setups requiring additional packages to work properly. ugh, hardware.

a common workaround is to install the linux-headers package and nvidia-dkms.

๐Ÿฆ‹ ARM, 32bit and other CPU types error out #1686, #2185

this is a bit of a catch-all known issue. officially x86_64 is the only architecture supported by Arch Linux. hence little effort has been put into supporting other platforms. it's not personal, it's justโ€ฆ scope.

in theory, other architectures should work, but small quirks might arise. โœจ

PRs are welcome but please be respectful of the delays in merging โ€” other fixes, issues or features will be prioritized for the above reasons. iykyk.

๐Ÿ—๏ธ Keyring is out of date #2213

missing key-issues tend to be that the archlinux-keyring package is out of date, usually as a result of an outdated ISO. there's an attempt from upstream to fix this issue, and it's the archlinux-keyring-wkd-sync.service.

the service starts almost immediately during boot, and if network is not configured in time โ€” the service will fail. subsequently the archinstall run might operate on an old keyring despite there being an update service for this. so rude.

there is really no way to reliably over time work around this issue in archinstall. instead, efforts to the upstream service should be considered the way forward. and/or keys not expiring between a sane amount of ISOs.

๐Ÿ’ก Note: the issue can happen on new ISO's too, even as little as a few days after release, as some keys might expire right after the keyring is "burnt in" to the ISO.
๐Ÿ’ก Note: another common issue relating to the network not being configured is that time might not be set correctly โ€” resulting in the keyring not being able to update. see Waiting for time sync #2144 above. ๐Ÿซถ

๐Ÿ“ฆ AUR packages

also a catch-all issue, bestie. AUR is unsupported, and until that changes we cannot use AUR packages to solve feature requests in archinstall. periodt.

this means that feature requests like supporting filesystems such as ZFS can not be added, and issues cannot be solved by using AUR packages either. sad but true.

๐Ÿ’ก Note: but in the spirit of giving the community options, archinstall supports Python Plugins (#archinstall-plugins), which means you can run archinstall --plugin <url> and source an AUR plugin.

torxed/archinstall-aur is a reference implementation for plugins:

# archinstall --plugin https://archlinux.life/aur-plugin

phisch/archinstall-aur is another alternative:

# archinstall --plugin https://raw.githubusercontent.com/phisch/archinstall-aur/master/archinstall-aur.py
โš ๏ธ Warning: this will allow for unsupported usage of AUR during installation. bestie i am BEGGING you to read that twice. ๐Ÿ‘€

๐Ÿ› REPORT ISSUES & BUGS ๐Ÿ›

issues and bugs should be reported over at <https://github.com/archlinux/archinstall/issues>. please and thank you ๐Ÿ’œ

general questions, enhancements and security issues can be reported over there too. for quick issues or if you need help, head over to the Discord server which has a help channel. we gotchu.

๐Ÿ“ Log files

when submitting a help ticket, please include the /var/log/archinstall/install.log. it can be found both on the live ISO, but also in the installed filesystem if the base packages were strapped in. literally just attach it, it makes everything so much faster.

๐Ÿ’ก Tip: an easy way to submit logs is archinstall share-log, which uploads install.log to paste.rs and prints a shareable URL. use caution when submitting other log files, but archinstall pledges to keep install.log safe for posting publicly! ๐Ÿซถ

there are additional log files under /var/log/archinstall/ that can be useful:

  • /var/log/archinstall/user_configuration.json โ€” stores most of the guided answers in the installer
  • /var/log/archinstall/user_credentials.json โ€” stores any usernames or passwords, can be passed to --creds
  • /var/log/archinstall/user_disk_layouts.json โ€” stores the chosen disks and their layouts
  • /var/log/archinstall/install.log โ€” a log file over what steps were taken by archinstall
  • /var/log/archinstall/cmd_history.txt โ€” a complete command history, command by command in order
  • /var/log/archinstall/cmd_output.txt โ€” a raw output from all the commands that were executed by archinstall
โš ๏ธ Warning: we only try to guarantee that /var/log/archinstall/install.log is free from sensitive information. any other log file should be pasted with utmost care! like, seriously. those others can have your whole life in them. ๐Ÿ˜ญ

๐ŸŒˆ DISCORD ๐ŸŒˆ

there's a discord channel which is frequented by some contributors. come hang out!!

to join the server, head over to <https://discord.gg/aDeMffrxNg> and join in. there's not many rules other than common sense and to treat others with respect. the general chat is for off-topic things as well, so bring your weirdest takes. ๐Ÿ’…

there's the @Party Animals role if you want notifications of new releases, which is posted in the #Release Party channel. another thing is the @Contributors role โ€” contributors can activate it by writing !verify and following the verification process.

hop in, we hope to see you there! : )


๐Ÿ PYTHON LIBRARY ๐Ÿ

archinstall ships on PyPi as archinstall. but the library can be installed manually as well. yes, she's a whole python package, main character energy. ๐Ÿ‘‘

โš ๏ธ Warning: these steps are not required if you want to use archinstall on the official Arch Linux ISO. the ISO already has her. don't do extra work for no reason bestie.

๐Ÿ“ฆ Installing with pacman

archinstall is on the official repositories. and it will also install archinstall as a python library. two for one, we love to see it.

to install both the library and the archinstall script:

pacman -S archinstall

alternatively, you can install only the library and not the helper executable using the python-archinstall package. pick your fighter. โญ

๐Ÿงš Installing from PyPI

the basic concept of PyPI applies, using pip:

pip install archinstall

๐Ÿ› ๏ธ Install using source code

you can also install using the source code. for sake of simplicity we will use git clone in this example:

git clone https://github.com/archlinux/archinstall

you can either move the folder into your project and simply do:

import archinstall

or you can use PyPA's build and installer to install it into pythons module path:

$ cd archinstall
$ python -m build .
$ python -m installer dist/*.whl

๐ŸŒˆ PYTHON MODULE ๐ŸŒˆ

okay bestie, so Archinstall supports running in module mode (https://docs.python.org/3/library/__main__.html). The way the library is invoked in module mode is limited to executing scripts under the scripts folder (https://github.com/archlinux/archinstall/tree/master/archinstall/scripts).

It's therefore important to place any script or profile you wish to invoke in the examples folder prior to building and installing. like, do not skip that part, iykyk ๐Ÿ’…

๐Ÿงš Pre-requisites ๐Ÿงš

We'll assume you've followed the Install using source code (#installing-python-manual) method. Before actually installing the library, you will need to place your custom installer-scripts under scripts (https://github.com/archlinux/archinstall/tree/master/archinstall/scripts) as a python file. yes, a whole python file, bestie โœจ

More on how you create these in the next section.

โš ๏ธ Warning: This is subject to change in the future as this method is currently a bit stiff. The script path will become a parameter. But for now, this is by design.

๐Ÿ› ๏ธ Creating a script ๐Ÿ› ๏ธ

Lets create a test_installer - installer as an example. This is assuming that the folder ./archinstall is a git-clone of the main repo. We begin by creating scripts/test_installer.py. The placement here is important later.

This script can now already be called using python -m archinstall --script test_installer after a successful installation of the library itself. But the script won't do much. So we'll do something simple like list all the hard drives as an example. lowkey useful, highkey iconic ๐ŸŒธ

To do this, we'll begin by importing archinstall in our scripts/test_installer.py and call a function within archinstall.

from archinstall.lib.disk.device_handler import device_handler
from pprint import pprint

pprint(device_handler.devices)

Now, go ahead and reference the Install using source code (#installing-python-manual) installation method. After running python -m archinstall --script test_installer it should print something that looks like:

[
    BDevice(
        disk=<parted.disk.Disk object at 0x7fbe17156050>,
        device_info=_DeviceInfo(
            model='PC801 NVMe SK hynix 512GB',
            path=PosixPath('/dev/nvme0n1'),
            type='nvme',
            total_size=Size(value=512110190592, unit=<Unit.B: 1>,
            sector_size=SectorSize(value=512, unit=<Unit.B: 1>)),
            free_space_regions=[
                <archinstall.lib.disk.device.DeviceGeometry object at 0x7fbe166c4250>,
                <archinstall.lib.disk.device.DeviceGeometry object at 0x7fbe166c4c50>,
                <archinstall.lib.disk.device.DeviceGeometry object at 0x7fbe166c4a10>],
            sector_size=SectorSize(value=512, unit=<Unit.B: 1>),
            read_only=False,
            dirty=False
        ),
        partition_infos=[
            _PartitionInfo(
                partition=<parted.partition.Partition object at 0x7fbe166c4a90>,
                name='primary',
                type=<PartitionType.PRIMARY: 'primary'>,
                fs_type=<FilesystemType.FAT32: 'fat32'>,
                path='/dev/nvme0n1p1',
                start=Size(value=2048, unit=<Unit.sectors: 'sectors'>, sector_size=SectorSize(value=512, unit=<Unit.B: 1>)),
                length=Size(value=535822336, unit=<Unit.B: 1>, sector_size=SectorSize(value=512, unit=<Unit.B: 1>)),
                flags=[
                    <PartitionFlag.BOOT: flag_id=1, alias=None>,
                    <PartitionFlag.ESP: flag_id=18, alias=None>
                ],
                partn=1,
                partuuid='a26be943-c193-41f4-9930-9341cf5f6b19',
                uuid='6EE9-2C00',
                disk=<parted.disk.Disk object at 0x7fbe17156050>,
                mountpoints=[
                    PosixPath('/boot')
                ],
                btrfs_subvol_infos=[]
            ),
            _PartitionInfo(...)
        ]
    )
]

That means your script is in the right place, and archinstall is working as intended. ate, no cap ๐Ÿ’š

๐Ÿ“ Note: Most calls, including the one above requires root (https://en.wikipedia.org/wiki/Superuser) privileges.

๐Ÿ”Œ PYTHON PLUGINS ๐Ÿ”Œ

archinstall supports plugins via two methods.

First method is directly via the --plugin parameter when running as a CLI tool. This will load a specific plugin locally or remotely via a path.

The second method is via Python's built in plugin discovery (https://packaging.python.org/en/latest/specifications/entry-points/) using entry points (https://docs.python.org/3/library/importlib.metadata.html#entry-points) categorized as archinstall.plugin.

๐Ÿ”Œ --plugin parameter ๐Ÿ”Œ

The parameter has the benefit of being stored in the --conf state, meaning when re-running an installation โ€” the plugin will automatically be loaded. Its limitation is that it requires an initial path to be known and written and be cumbersome. so real ๐Ÿ˜ญ

๐Ÿฆ‹ Plugin Discovery ๐Ÿฆ‹

This method allows for multiple plugins to be loaded with the drawback that they have to be installed beforehand on the system running archinstall. This mainly targets those who build their own ISO's and package specific setups for their needs.

๐Ÿ‘‘ What's supported? ๐Ÿ‘‘

Currently the documentation for this is scarce. Until that is resolved, the best way to find supported features is to search the source code for plugin.on_ (https://github.com/search?q=repo%3Aarchlinux%2Farchinstall+%22plugin.on_%22&type=code) as this will give a clear indication of which calls are made to plugins.

๐Ÿง  How does it work? ๐Ÿง 

archinstall plugins use a discovery-driven approach where plugins are queried for certain functions. As an example, if a plugin has the following function:

def on_pacstrap(*packages):
    ...

The function archinstall.Pacman().strap(["some packages"]) is hardcoded to iterate plugins and look for on_pacstrap in the plugin. If the function exists, .strap() will call the plugin's function and replace the initial package list with the result from the plugin.

The best way to document these calls is currently undecided, as it's hard to document this behavior dynamically.

๐ŸŽ€ Writing your own? ๐ŸŽ€

The simplest way currently is to look at a reference implementation or the community. Two of these are:

And search for plugin.on_ (https://github.com/search?q=repo%3Aarchlinux%2Farchinstall+%22plugin.on_%22&type=code) in the code base to find what archinstall will look for. PR's are welcome to widen the support for this. community slay ๐ŸŒˆ


๐Ÿ› ๏ธ ARCHINSTALL.INSTALLER ๐Ÿ› ๏ธ

The installer is the main class for accessing an installation-instance. You can look at this class as the installation you have or will perform.

Anything related to inside the installation, will be found in this class.

class archinstall.lib.installer.Installer(target: Path, disk_config: DiskLayoutConfiguration, base_packages: list[str] | None = None, kernels: list[str] | None = None, firmware: list[str] | None = None, silent: bool = False)

๐ŸŒธ Author ๐ŸŒธ

Anton Hvornum

2022, Anton Hvornum


okay bestie, that's the whole page โ€” this is ARCHINSTALL(1), dated Sep 29, 2026. periodt ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from