2012-06-18 03:17:10 +08:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
#
|
|
|
|
# Assumptions:
|
|
|
|
# 1) User has partitioned, formatted, and mounted partitions on /mnt
|
|
|
|
# 2) Network is functional
|
|
|
|
# 3) Arguments passed to the script are valid pacman targets
|
|
|
|
# 4) A valid mirror appears in /etc/pacman.d/mirrorlist
|
|
|
|
#
|
|
|
|
|
2012-06-18 05:52:39 +08:00
|
|
|
shopt -s extglob
|
|
|
|
|
2012-07-14 21:33:46 +08:00
|
|
|
hostcache=0
|
2012-09-15 23:46:48 +08:00
|
|
|
copykeyring=1
|
2022-08-20 02:04:41 +08:00
|
|
|
initkeyring=0
|
2012-09-15 23:46:48 +08:00
|
|
|
copymirrorlist=1
|
2022-10-25 16:58:47 +08:00
|
|
|
pacman_args=()
|
2019-08-06 12:22:35 +08:00
|
|
|
pacmode=-Sy
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
setup=chroot_setup
|
2022-07-28 22:02:31 +08:00
|
|
|
unshare=0
|
2022-10-22 20:40:35 +08:00
|
|
|
copyconf=0
|
|
|
|
pacman_config=/etc/pacman.conf
|
2012-06-18 03:17:10 +08:00
|
|
|
|
2023-03-27 00:57:04 +08:00
|
|
|
m4_include(common)
|
|
|
|
|
2012-06-18 05:52:39 +08:00
|
|
|
usage() {
|
|
|
|
cat <<EOF
|
2012-07-15 22:04:49 +08:00
|
|
|
usage: ${0##*/} [options] root [packages...]
|
2012-06-18 05:52:39 +08:00
|
|
|
|
|
|
|
Options:
|
2019-06-06 03:26:49 +08:00
|
|
|
-C <config> Use an alternate config file for pacman
|
2012-06-23 01:14:09 +08:00
|
|
|
-c Use the package cache on the host, rather than the target
|
2022-10-25 16:58:47 +08:00
|
|
|
-D Skip pacman dependency checks
|
2012-09-15 23:46:48 +08:00
|
|
|
-G Avoid copying the host's pacman keyring to the target
|
2019-01-06 00:19:30 +08:00
|
|
|
-i Prompt for package confirmation when needed (run interactively)
|
2022-08-20 02:04:41 +08:00
|
|
|
-K Initialize an empty pacman keyring in the target (implies '-G')
|
2012-09-15 23:46:48 +08:00
|
|
|
-M Avoid copying the host's mirrorlist to the target
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
-N Run in unshare mode as a regular user
|
2022-10-22 20:40:35 +08:00
|
|
|
-P Copy the host's pacman config to the target
|
2019-08-06 12:22:35 +08:00
|
|
|
-U Use pacman -U to install packages
|
2012-07-15 22:04:49 +08:00
|
|
|
|
2012-11-13 10:00:09 +08:00
|
|
|
-h Print this help message
|
|
|
|
|
2012-07-15 22:04:49 +08:00
|
|
|
pacstrap installs packages to the specified new root directory. If no packages
|
|
|
|
are given, pacstrap defaults to the "base" group.
|
2012-06-18 05:52:39 +08:00
|
|
|
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
if [[ -z $1 || $1 = @(-h|--help) ]]; then
|
|
|
|
usage
|
|
|
|
exit $(( $# ? 0 : 1 ))
|
|
|
|
fi
|
|
|
|
|
2022-10-25 16:58:47 +08:00
|
|
|
while getopts ':C:cDGiKMNPU' flag; do
|
2012-06-18 03:17:10 +08:00
|
|
|
case $flag in
|
2012-10-04 10:55:49 +08:00
|
|
|
C)
|
|
|
|
pacman_config=$OPTARG
|
|
|
|
;;
|
2022-10-25 16:58:47 +08:00
|
|
|
D)
|
|
|
|
pacman_args+=(-dd)
|
|
|
|
;;
|
2012-06-23 01:14:09 +08:00
|
|
|
c)
|
2012-07-14 21:33:46 +08:00
|
|
|
hostcache=1
|
2012-06-23 01:14:09 +08:00
|
|
|
;;
|
2012-07-27 07:57:11 +08:00
|
|
|
i)
|
|
|
|
interactive=1
|
|
|
|
;;
|
2012-09-15 23:46:48 +08:00
|
|
|
G)
|
|
|
|
copykeyring=0
|
|
|
|
;;
|
2022-08-20 02:04:41 +08:00
|
|
|
K)
|
|
|
|
initkeyring=1
|
|
|
|
;;
|
2012-09-15 23:46:48 +08:00
|
|
|
M)
|
|
|
|
copymirrorlist=0
|
|
|
|
;;
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
N)
|
|
|
|
setup=unshare_setup
|
2022-07-28 22:02:31 +08:00
|
|
|
unshare=1
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
;;
|
2022-10-22 20:40:35 +08:00
|
|
|
P)
|
|
|
|
copyconf=1
|
|
|
|
;;
|
2019-08-06 12:22:35 +08:00
|
|
|
U)
|
|
|
|
pacmode=-U
|
|
|
|
;;
|
2012-06-18 22:05:40 +08:00
|
|
|
:)
|
|
|
|
die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
|
|
|
|
;;
|
2012-06-18 03:17:10 +08:00
|
|
|
?)
|
|
|
|
die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
shift $(( OPTIND - 1 ))
|
|
|
|
|
2012-07-15 22:04:49 +08:00
|
|
|
(( $# )) || die "No root directory specified"
|
|
|
|
newroot=$1; shift
|
2022-10-25 16:58:47 +08:00
|
|
|
pacman_args+=("$pacmode" "${@:-base}" --config="$pacman_config")
|
2012-06-23 01:14:09 +08:00
|
|
|
|
|
|
|
if (( ! hostcache )); then
|
|
|
|
pacman_args+=(--cachedir="$newroot/var/cache/pacman/pkg")
|
2012-06-18 03:17:10 +08:00
|
|
|
fi
|
|
|
|
|
2012-07-27 07:57:11 +08:00
|
|
|
if (( ! interactive )); then
|
|
|
|
pacman_args+=(--noconfirm)
|
|
|
|
fi
|
|
|
|
|
2012-06-18 11:45:46 +08:00
|
|
|
[[ -d $newroot ]] || die "%s is not a directory" "$newroot"
|
2012-06-18 03:17:10 +08:00
|
|
|
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
pacstrap() {
|
|
|
|
(( EUID == 0 )) || die 'This script must be run with root privileges'
|
|
|
|
|
|
|
|
# create obligatory directories
|
|
|
|
msg 'Creating install root at %s' "$newroot"
|
|
|
|
mkdir -m 0755 -p "$newroot"/var/{cache/pacman/pkg,lib/pacman,log} "$newroot"/{dev,run,etc/pacman.d}
|
|
|
|
mkdir -m 1777 -p "$newroot"/tmp
|
|
|
|
mkdir -m 0555 -p "$newroot"/{sys,proc}
|
2012-06-18 03:17:10 +08:00
|
|
|
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
# mount API filesystems
|
|
|
|
$setup "$newroot" || die "failed to setup chroot %s" "$newroot"
|
2012-06-18 03:27:38 +08:00
|
|
|
|
2022-08-20 02:04:41 +08:00
|
|
|
if [[ ! -d $newroot/etc/pacman.d/gnupg ]]; then
|
|
|
|
if (( initkeyring )); then
|
|
|
|
pacman-key --gpgdir "$newroot"/etc/pacman.d/gnupg --init
|
|
|
|
elif (( copykeyring )) && [[ -d /etc/pacman.d/gnupg ]]; then
|
|
|
|
# if there's a keyring on the host, copy it into the new root
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
cp -a --no-preserve=ownership /etc/pacman.d/gnupg "$newroot/etc/pacman.d/"
|
|
|
|
fi
|
2012-09-15 23:46:48 +08:00
|
|
|
fi
|
2012-06-18 03:17:10 +08:00
|
|
|
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
msg 'Installing packages to %s' "$newroot"
|
2022-10-25 16:58:47 +08:00
|
|
|
if ! $pid_unshare pacman -r "$newroot" "${pacman_args[@]}"; then
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
die 'Failed to install packages to new root'
|
|
|
|
fi
|
pacstrap: try to copy the host keyring before installing packages
When there is no keyring in the new root, attempting to install e.g.
archlinux-keyring will result in the post-install script silently
failing to do anything (because there are no keys, and, critically, no
secret keys). The potentially very outdated keyring is then copied over
from the host, secret key and all, so subsequent pacman operations have
a trusted keyring that is at least as recent as the ISO or other host
system... but if there has been a keyring update between the date of the
ISO creation and the date of the install, those keys will continue to be
missing until the next keyring update, resulting in a bad out-of-the-box
experience.
This also means that if a thirdparty keyring package was scheduled to be
installed, it will not be populated at all; this affects downstream
archlinux32 build chroots.
There's no reason to delay this until after packages are installed -- we
aren't afraid of e.g. the mirrorlist resulting in file conflicts due to
a packaged pacman-mirrorlist, because the gnupg configuration should not
be getting packaged directly.
Fixes FS#61296 FS#61304 FS#61309 FS#61312 FS#62355
2018-12-05 06:32:50 +08:00
|
|
|
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
if (( copymirrorlist )); then
|
|
|
|
# install the host's mirrorlist onto the new root
|
|
|
|
cp -a /etc/pacman.d/mirrorlist "$newroot/etc/pacman.d/"
|
|
|
|
fi
|
2022-10-22 20:40:35 +08:00
|
|
|
|
|
|
|
if (( copyconf )); then
|
|
|
|
cp -a "$pacman_config" "$newroot/etc/pacman.conf"
|
|
|
|
fi
|
Add unshare mode to pacstrap
This adds an "unshare" mode to pacstrap. This mode lets a regular user
create a new arch root filesystem. We use -N because both -U and -u are
taken in pacstrap and arch-chroot, respectively. There are two major
changes to pacstrap: we need to run many commands in under unshare, and
the setup process for mounts is different.
Because unshare starts a new shell, it is difficult to run many commands
in sequence. To get around this, we create a function for the rest of
the commands we wish to run, and then declare all functions and
variables in the unshare'd shell. This is pretty convenient. An
alternative method would be to generate the shell script as a HERE
document, and pipe it to bash.
Because unshare starts a new shell, we can only communicate using
stdin/out and any command line arguments. And we need to defer some
setup until after we are root. To get around this, we create a function
for the rest of the commands we wish to run, and then declare all
functions and variables in the unshare'd shell. I also considered having
a separate helper script which would contain the contents of pacstrap().
But I think this would be confusing, because the logic would then live
in a separate file (instead of just a separate function). That method is
also tricky because every variable has to be passed in through the
command-line arguments. One last method would be to generate a script on
the fly (e.g. using a HERE doc). I think that method could work as well.
The primary difference to the setup process is that we need to mount
filesystems in a different manner:
- We bind-mount the root directory. This is so commands which want to
determine how much free space there is (or otherwise work with mounts)
expect a mount on /. We unmount it with --lazy, since otherwise sys
will cause an error (see below).
- proc can be mounted multiple times and is mounted in the same way
- sys cannot be mounted again, but we can recursively bind-mount it.
When mounted this way, we can't unmount it until the mount namespace
is deleted (likely because sys has a number of sub-mounts), so we have
to use --lazy when unmounting it.
- dev can be bind-mounted, but this results in errors because some
packages try and modify files in /dev if they exist. Since we don't
have permission to do that on the host system, this fails. Instead, we
just bind-mount a minimal set of files.
- run is not bind-mounted, but is instead created as a new tmpfs.
According to aea51ba ("Bind mount /run from host into new root"), the
reason this was done was to avoid lengthy timeouts when scanning for
lvm devices. Because unshare does not (and cannot) use lvm devices, we
don't need to bind-mount.
- tmp is created as usual.
Closes: #8
2021-10-18 05:13:31 +08:00
|
|
|
}
|
|
|
|
|
2022-07-28 22:02:31 +08:00
|
|
|
if (( unshare )); then
|
|
|
|
$mount_unshare bash -c "$(declare_all); pacstrap"
|
|
|
|
else
|
|
|
|
pacstrap
|
|
|
|
fi
|
2012-06-20 02:34:01 +08:00
|
|
|
|
2012-06-18 04:05:18 +08:00
|
|
|
# vim: et ts=2 sw=2 ft=sh:
|