#1101148 debian-installer: "Download error" on "d-i apt-setup/local#/key" preventing installation from local/private repo

Package:
debian-installer
Source:
debian-installer
Description:
Debian Installer documentation
Submitter:
Debian Admin
Date:
2025-08-13 05:05:01 UTC
Severity:
normal
Tags:
#1101148#5
Date:
2025-03-23 22:22:18 UTC
From:
To:
Dear Maintainer,

When mirroring Debian locally and signing with local GPG/PGP keys, the debian-installer fails on a critical "Download error" in the syslog file of the debian-installer for the "d-i apt-setup/local0/key string [URL]" step, preventing the installation from proceeding. Also tried providing the key in-line in base64 in the same "d-i" step, but could not get this working either. After much testing, tweaking, and reviewing the sample preseed files and "debian-installer" source code, this appears to be a bug with the debian-installer.

- https://www.debian.org/releases/stable/example-preseed.txt
- https://www.debian.org/releases/bookworm/example-preseed.txt
- https://www.debian.org/releases/bullseye/example-preseed.txt
- https://salsa.debian.org/installer-team/apt-setup/-/blob/master/generators/60local?ref_type=heads

Below is the preseed file used to install this Debian system, which the issue was encountered on, however it is also present on Debian 11 Bullseye

### START PRESEED FILE ###
# Debian sample
# https://www.debian.org/releases/stable/example-preseed.txt

# Preseeding only locale sets language, country and locale.
d-i debian-installer/locale string en_US

# Keyboard selection.
# Disable automatic (interactive) keymap detection.
d-i console-setup/ask_detect boolean false
d-i keyboard-configuration/xkb-keymap select us
d-i keyboard-configuration/toggle select No toggling
d-i keyboard-configuration/layoutcode string us
d-i keyboard-configuration/variantcode string

# netcfg will choose an interface that has link if possible. This makes it
# skip displaying a list if there is more than one interface.
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string Debian12.9-x86-64

# If non-free firmware is needed for the network or other hardware, you can
# configure the installer to always try to load it, without prompting. Or
# change to false to disable asking.
# d-i hw-detect/load_firmware boolean true

# NTP/Time Setup
d-i time/zone string US/Eastern
d-i clock-setup/utc boolean true
d-i clock-setup/ntp boolean true
d-i clock-setup/ntp-server  string ntp.ubuntu.com

# Setup the installation source
d-i mirror/country string manual
d-i mirror/http/hostname string 10.0.0.10
d-i mirror/http/directory string /cblr/links/Debian12.9-x86_64
d-i mirror/http/proxy string


# Suite to install.
# d-i mirror/suite string precise
# d-i mirror/udeb/suite string precise

# Components to use for loading installer components (optional).
#d-i mirror/udeb/components multiselect main, restricted

# Disk Partitioning
# Use LVM, and wipe out anything that already exists
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman-efi/non_efi_system boolean true
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-partitioning/confirm_write_new_label boolean true

# You can choose one of the three predefined partitioning recipes:
# - atomic: all files in one partition
# - home:   separate /home partition
# - multi:  separate /home, /usr, /var, and /tmp partitions
d-i partman-auto/choose_recipe select atomic

# If you just want to change the default filesystem from ext3 to something
# else, you can do that without providing a full recipe.
# d-i partman/default_filesystem string ext4

# root account and password
d-i passwd/root-login boolean true
d-i passwd/root-password-crypted password [REDACTED]

# skip creation of a normal user account.
d-i passwd/make-user boolean true
d-i passwd/user-fullname string Debian Admin
d-i passwd/username string debian
d-i passwd/user-password-crypted password [REDACTED]

# You can choose to install restricted and universe software, or to install
# software from the backports repository.
# d-i apt-setup/restricted boolean true
# d-i apt-setup/universe boolean true
# d-i apt-setup/backports boolean true

# Uncomment this if you don't want to use a network mirror.
# d-i apt-setup/use_mirror boolean false

# Select which update services to use; define the mirrors to be used.
# Values shown below are the normal defaults.
d-i apt-setup/services-select multiselect

# Additional repositories, local[0-9] available


# Enable deb-src lines
# d-i apt-setup/local0/source boolean true

# URL to the public key of the local repository; you must provide a key or
# apt will complain about the unauthenticated repository and so the
# sources.list line will be left commented out
d-i apt-setup/local0/repository string http://10.0.0.10/cblr/links/Debian12.9-x86_64
d-i apt-setup/local0/key string http://10.0.0.10/cblr/pub/cobbler.gpg.asc

# By default the installer requires that repositories be authenticated
# using a known gpg key. This setting can be used to disable that
# authentication. Warning: Insecure, not recommended.
d-i debian-installer/allow_unauthenticated boolean true

# Package selection
# Default for minimal
tasksel tasksel/first multiselect standard
# Default for server
# tasksel tasksel/first multiselect standard, web-server
# Default for gnome-desktop
# tasksel tasksel/first multiselect standard, gnome-desktop

# Individual additional packages to install
# wget is REQUIRED otherwise quite a few things won't work
# later in the build (like late-command scripts)
d-i pkgsel/include string wget curl openssh-server sudo vim
popularity-contest popularity-contest/participate boolean false

# Debian needs this for the installer to avoid any question for grub
# Please verify that it suit your needs as it may overwrite any usb stick
d-i grub-installer/grub2_instead_of_grub_legacy boolean true
d-i grub-installer/bootdev string default
d-i grub-installer/with_other_os boolean true
d-i grub-installer/force-efi-extra-removable boolean false
d-i grub-installer/enable_os_prober_otheros_yes boolean false
d-i grub-installer/enable_os_prober_otheros_no boolean true

# Use the following option to add additional boot parameters for the
# installed system (if supported by the bootloader installer).
# Note: options passed to the installer will be added automatically.
d-i debian-installer/add-kernel-opts string

# Avoid that last message about the install being complete.
d-i finish-install/reboot_in_progress note


# This first command is run as early as possible, just after preseeding is read.
# d-i preseed/early_command string [command]
d-i preseed/early_command string wget -O- \
http://10.0.0.10/cblr/svc/op/script/profile/Debian12.9-x86_64/?script=preseed_early_unauthenticated | \
   /bin/sh -s

# This command is run immediately before the partitioner starts. It may be
# useful to apply dynamic partitioner preseeding that depends on the state
# of the disks (which may not be visible when preseed/early_command runs).
# d-i partman/early_command \
#       string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"

# This command is run just before the install finishes, but when there is
# still a usable /target directory. You can chroot to /target and use it
# directly, or use the apt-install and in-target commands to easily install
# packages and run commands in the target system.
# d-i preseed/late_command string [command]
d-i preseed/late_command string wget -O- \
http://10.0.0.10/cblr/svc/op/script/profile/Debian12.9-x86_64/?script=preseed_late_bookworm | \
   chroot /target /bin/sh -s
### END PRESEED FILE ###

However, using the below script to download the key manually during the "d-i preseed/early_command" the installation completes successfully as expected. The script is simple and closely mirrors what the debian-installer "local60" script effectively does, which is responsible for downloading the repo key.

### START PRESEED EARLY SCRIPT ###
wget "http://10.0.0.10/cblr/svc/op/trig/mode/pre/profile/Debian12.9-x86_64" -O /dev/null

while true; do
        [ -d /target/etc/apt/trusted.gpg.d ] && cd /target/etc/apt/trusted.gpg.d && fetch-url http://10.0.0.10/cblr/pub/cobbler.gpg.asc cobbler.gpg.asc && exit;
        echo nope;
        sleep 1;
done 2> /dev/null 1> /dev/null &
### END PRESEED EARLY SCRIPT ###

There is an old bug report related to this step in "d-i" from 2016, but it states that the download works as expected, but I have not found that to be the case

- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=839248

#1101148#10
Date:
2025-03-25 18:44:51 UTC
From:
To:
To clarify, this occurs when installing Debian 11 or 12 (tested so far)
over the network from a privately hosted and signed repo. In my case, the
repo was extracted from the Debian 12 disk 1 installation media (ISO file)
which is not signed from Debian (source: https://wiki.debian.org/SecureApt
) so the repo must be signed with a local keypair, which debian-installer
will not trust natively during network installs. In my case, the associate
public key used to verify the repo was made available over HTTP on the same
server that the repo is hosted from and specified in the preseed file.

Additionally, the "d-i debian-installer/allow_unauthenticated" option is
set to "true" but this appears to only apply to the "d-i
mirror/http/hostname" & "d-i mirror/http/directory" options, not the "d-i
apt-setup" options from my experience.

Regarding the  "d-i preseed/early_command" script included in the original
bug report, the "wget" command can be ignored since the "while" loop is the
full workaround solution.

More steps to reproduce the issue as well as additional references to
Debian official docs can be found on a community post I authored for
Cobbler, a PXE boot server application I used for hosting the repo and PXE
boot resources:
https://cobbler.github.io/blog/2024/12/02/Cobbler-v3.3.7-Debian-Deployment-Guide.html
- on a related note, I think it could be beneficial to link to this article
in Debian's Automated Installation documentation where cobbler is already
mentioned: https://wiki.debian.org/AutomatedInstallation

#1101148#15
Date:
2025-05-11 00:08:21 UTC
From:
To:
Hi all,

Did some more troubleshooting and determined the root cause of this issue;
the trouble is with the *base-installer* package (
https://salsa.debian.org/installer-team/base-installer ) not *apt-setup*. I
have registered for an account on https://salsa.debian.org/ so that I can
just open an issue on the repo there if I do not hear anything back on this
bug by the time my account is approved. For clarity, the title of this bug
is not entirely accurate to the issue, and my previous descriptions here
can be mostly disregarded.

*The real issue:* Debian's official latest preseed instructions
<https://www.debian.org/releases/stable/amd64/apbs04.en.html> lists the
option *d-i debian-installer/allow_unauthenticated boolean true* which is
referenced in the file library.sh
<https://salsa.debian.org/installer-team/base-installer/-/blob/master/library.sh>
in
Debian's installer to configure some settings in *atp.conf.d* within the
install target system's */etc/apt* directory. From what I could find, there
is no way to provide a public key for the main install mirror (preseed
settings *d-i **mirror/http/hostname *& *d-i **mirror/http/directory*) or
omit that main mirror and just use the additional mirrors, which do allow
providing a GPG public key (*d-i apt-setup/local0/repository *& *d-i
apt-setup/local0/key*). It appears the intended way to use an unsigned
mirror as the main installation mirror is just to use the
"allow_unauthenticated" option described above. However, after reviewing
the man pages for apt-get
<https://manpages.debian.org/bookworm/apt/apt-get.8.en.html> & apt-secure
<https://manpages.debian.org/bookworm/apt/apt-secure.8.en.html>, I
concluded that he library.sh
<https://salsa.debian.org/installer-team/base-installer/-/blob/master/library.sh>
file mentioned above is missing the *Acquire::AllowInsecureRepositories
"true";* entry to the *00AllowUnauthenticated* file, in addition to
the *APT::Get::AllowUnauthenticated
"true";* & *Aptitude::CmdLine::Ignore-Trust-Violations "true";* options
which are already set.

Specifically, apt's *update* command will fail to fetch the available
packages from the source, since *apt-get update* specifically requires the
*Acquire::AllowInsecureRepositories* flag enabled (not necessary for apt's
*update* or *install *commands) to query an unsigned repo. this causes a
non-fatal failure when updating apt's cache in the *apt_update* function in
library.sh
<https://salsa.debian.org/installer-team/base-installer/-/blob/master/library.sh>
and
ultimately fails to detect an available kernel to install from the repo in
the *pick_kernel* function in library.sh
<https://salsa.debian.org/installer-team/base-installer/-/blob/master/library.sh>,
retuening a fatal "no-kernel-found" error.

This fix can be confirmed by using the following script in the *d-i
**preseed/early_command
string* value:

```
while true; do
    [ -f /usr/lib/base-installer/library.sh ] && \
        sed -i 's,APT::Get::AllowUnauthenticated
"true";,APT::Get::AllowUnauthenticated
"true";\nAcquire::AllowInsecureRepositories "true";,'
/usr/lib/base-installer/library.sh && \
        break;
    sleep 1;
done &
```

This all assumes that installing Debian Bookworm and/or Bullseye from an
unauthenticated/insecure repo mirror is intended to be officially
supported. The solution provided above is the simplest in my opinion, but
could also be accomplished by adding a completely separate preseed value
for "AllowInsecureRepositories" *(a bit excessive if you ask me)* or
providing a mechanism to preseed a private repo's GPG public key/keyring
for an automated install, although this would not fully solve the problem
with installing from an unsigned repo.

Thank you for your time and attention.

#1101148#20
Date:
2025-07-11 16:02:58 UTC
From:
To:
Does this background work for you?

I'm trying this on the daily trixie netinst and the installer gets
stuck on 'Detect and mount installation media'.

Inspecting the process list; the preseed/early_command does not seem
to background the script or process.

I've tried the snippet inline and in a script that backgrounds itself
(loop), and even that the preseed has an '&' but always the same
result.

I'm having a similar issue where apt-setup wants to access a local key
that is on the cdrom, but I have yet to find a way to copy it onto the
the target for apt-setup to pick it up (late_command is too late since
apt-setup will have failed by then).

Use case: I want to use the CD repository to be able to install and to
be used by pbuilder. For the latter, I have self-signed the image
Release files; but by doing that, I'm running into apt-setup that uses
the keys on the /target and that key is not there yet.

So either I get pbuilder to work with the singed repository, or I get
the iso installer to work with the unsigned repository.

#1101148#25
Date:
2025-08-13 05:02:31 UTC
From:
To:
 You were very close to the solution. I haven't tested it on trixie , but
it definitely works on bookworm

d-i partman/early_command string apt-install gnupg ; \
wget -O /usr/share/keyrings/public.gpg https://{{ pulp_url
}}/pulp/content/gpg/public.gpg ; \
echo -e "cp /usr/share/keyrings/public.gpg
/target/tmp/samokat-deb-release-public.gpg\nchroot /target /bin/bash
/bin/apt-key add /tmp/public.gpg" >
/usr/lib/apt-setup/generators/001add-key ; \
chmod +x /usr/lib/apt-setup/generators/001add-key ; \