3

I've performed the following test on a docker alpine linux:

ole@MKI:~$ docker run --rm -it alpine /bin/ash
/ # apk add --update duplicity
fetch http://dl-4.alpinelinux.org/alpine/v3.3/main/x86_64/APKINDEX.tar.gz
fetch http://dl-4.alpinelinux.org/alpine/v3.3/community/x86_64/APKINDEX.tar.gz
(1/28) Installing libbz2 (1.0.6-r4)
(2/28) Installing expat (2.1.0-r2)
...
(28/28) Installing duplicity (0.7.05-r0)
Executing busybox-1.24.1-r7.trigger
OK: 72 MiB in 39 packages
/ # gpg --list-keys
gpg: directory '/root/.gnupg' created
gpg: new configuration file '/root/.gnupg/dirmngr.conf' created
gpg: new configuration file '/root/.gnupg/gpg.conf' created
gpg: WARNING: options in '/root/.gnupg' are not yet active during this run
gpg: keybox '/root/.gnupg/pubring.kbx' created
gpg: /root/.gnupg/trustdb.gpg: trustdb created
/ # gpg --list-keys
/ # gpg --gen-key
gpg (GnuPG) 2.1.10; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg2 --full-gen-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: Testing
Email address: testing@test
You selected this USER-ID:
"Testing <testing@test>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: agent_genkey failed: No such file or directory
Key generation failed: No such file or directory
/ # ls /root/.gnupg/
S.gpg-agent dirmngr.conf gpg.conf private-keys-v1.d pubring.kbx trustdb.gpg
/ #

Any idea as to why the key generation is failing?

[Edit] I could always just generate the keys using an ubuntu image and mount them in a volume. That's ultimately what I'm doing anyways, but I thought it would nice to have this working with the alpine image so I pasted the strace below as suggested:

/ # strace -f gpg --gen-key
execve("/usr/bin/gpg", ["gpg", "--gen-key"], [/* 6 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f75271edda8) = 0
set_tid_address(0x7f75271edde0)         = 17
open("/etc/ld-musl-x86_64.path", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libz.so.1", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=87976, ...}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0!\0\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2187264, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f7526d4f000
mmap(0x7f7526f63000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x14000) = 0x7f7526f63000
close(3)                                = 0
open("/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=856824, ...}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\214\0\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2957312, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f7526a7d000
mmap(0x7f7526d45000, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xc8000) = 0x7f7526d45000
mmap(0x7f7526d4e000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7526d4e000
close(3)                                = 0
open("/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=67520, ...}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p'\0\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2166784, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f752686c000
mmap(0x7f7526a7b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xf000) = 0x7f7526a7b000
close(3)                                = 0
open("/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFREG|0755, st_size=67616, ...}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\2204\0\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2166784, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f752665b000
mmap(0x7f752686a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xf000) = 0x7f752686a000
close(3)                                = 0
mprotect(0x7f7526f63000, 4096, PROT_READ) = 0
mprotect(0x7f7526d45000, 4096, PROT_READ) = 0
mprotect(0x7f7526a7b000, 4096, PROT_READ) = 0
mprotect(0x7f752686a000, 4096, PROT_READ) = 0
mprotect(0x7f75271ec000, 4096, PROT_READ) = 0
mprotect(0x7f752749a000, 8192, PROT_READ) = 0
fstat(0, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0
fstat(2, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0
access("/etc/gcrypt/fips_enabled", F_OK) = -1 ENOENT (No such file or directory)
open("/proc/sys/crypto/fips_enabled", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/gcrypt/hwf.deny", O_RDONLY)  = -1 ENOENT (No such file or directory)
prlimit64(0, RLIMIT_CORE, NULL, {rlim_cur=0, rlim_max=RLIM64_INFINITY}) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[], NULL, 8) = 0
prlimit64(0, RLIMIT_CORE, {rlim_cur=0, rlim_max=RLIM64_INFINITY}, NULL) = 0
futex(0x7f75271f011c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 8) = 0
rt_sigaction(SIGINT, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGHUP, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGHUP, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGTERM, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGSEGV, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGSEGV, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGUSR1, {0x7f752726a0d4, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0
mmap(NULL, 32768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7527492000
getuid()                                = 0
mlock(0x7f7527492000, 32768)            = 0
access("/root/.gnupg/gpg.conf-2.1.10", R_OK) = -1 ENOENT (No such file or directory)
access("/root/.gnupg/gpg.conf-2.1", R_OK) = -1 ENOENT (No such file or directory)
access("/root/.gnupg/gpg.conf-2", R_OK) = -1 ENOENT (No such file or directory)
access("/root/.gnupg/gpg.conf", R_OK)   = -1 ENOENT (No such file or directory)
access("/root/.gnupg/options", R_OK)    = -1 ENOENT (No such file or directory)
stat("~/.gnupg", 0x7fff3556cc38)        = -1 ENOENT (No such file or directory)
stat("/root/.gnupg/gpg.conf", 0x7fff3556cc38) = -1 ENOENT (No such file or directory)
open("/root/.gnupg/gpg.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
writev(2, [{"", 0}, {"gpg (GnuPG) 2.1.10; Copyright (C"..., 69}], 2gpg (GnuPG) 2.1.10; Copyright (C) 2015 Free Software Foundation, Inc.) = 69
writev(2, [{"", 0}, {"\n", 1}], 2
)      = 1
writev(2, [{"", 0}, {"This is free software: you are f"..., 121}], 2This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
) = 121
writev(2, [{"", 0}, {"\n", 1}], 2
)      = 1
access("/root/.gnupg/random_seed", F_OK) = -1 ENOENT (No such file or directory)
open("/root/.gnupg/pubring.gpg", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/root/.gnupg/pubring.kbx", O_RDONLY) = -1 ENOENT (No such file or directory)
access("/root/.gnupg/pubring.kbx", F_OK) = -1 ENOENT (No such file or directory)
access("/root/.gnupg", F_OK)            = -1 ENOENT (No such file or directory)
mkdir("/root/.gnupg", 0700)             = 0
write(2, "gpg: directory '/root/.gnupg", 28gpg: directory '/root/.gnupg) = 28
write(2, "' created\n", 10' created
)             = 10
open("/usr/share/gnupg/dirmngr-conf.skel", O_RDONLY) = 3
umask(077)                              = 022
open("/root/.gnupg/dirmngr.conf", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
ioctl(4, TIOCGWINSZ, 0x7fff3556c908)    = -1 ENOTTY (Not a tty)
umask(022)                              = 077
readv(3, [{"", 0}, {"# dirmngr-conf.skel - Skeleton t"..., 1024}], 2) = 1024
readv(3, [{"", 0}, {"nd receive keys to and from a ke"..., 1024}], 2) = 1024
writev(4, [{"# dirmngr.conf - Options for Dir"..., 1024}, {"L", 1}], 2) = 1025
readv(3, [{"", 0}, {" and only one is a Tor hidden\n# "..., 1024}], 2) = 704
writev(4, [{"DAP\n# support).\n#\n# Example HKP "..., 1024}, {"c", 1}], 2) = 1025
readv(3, [{"", 0}, {" and only one is a Tor hidden\n# "..., 1024}], 2) = 0
writev(4, [{"ally running or not (on a per se"..., 593}, {NULL, 0}], 2) = 593
close(4)                                = 0
close(3)                                = 0
write(2, "gpg: new configuration file '/ro"..., 54gpg: new configuration file '/root/.gnupg/dirmngr.conf) = 54
write(2, "' created\n", 10' created
)             = 10
open("/usr/share/gnupg/gpg-conf.skel", O_RDONLY) = 3
umask(077)                              = 022
open("/root/.gnupg/gpg.conf", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
ioctl(4, TIOCGWINSZ, 0x7fff3556c908)    = -1 ENOTTY (Not a tty)
umask(022)                              = 077
readv(3, [{"", 0}, {"# These first three lines are no"..., 1024}], 2) = 1024
readv(3, [{"", 0}, {"\n\n# Uncomment the following opti"..., 1024}], 2) = 1024
writev(4, [{"# Options for GnuPG\n# Copyright "..., 1024}, {"o", 1}], 2) = 1025
readv(3, [{"", 0}, {"nce you may want to use this opt"..., 1024}], 2) = 1024
writev(4, [{"re than 1 secret key in your key"..., 1024}, {" ", 1}], 2) = 1025
readv(3, [{"", 0}, {"\n# \"0x12345678\".  Note there is "..., 1024}], 2) = 1024
writev(4, [{"subkey, ensure that the cross\n# "..., 1024}, {"o", 1}], 2) = 1025
readv(3, [{"", 0}, {"r.\n#\n# verbose = show more infor"..., 1024}], 2) = 1024
writev(4, [{" another group.  Note also that\n"..., 1024}, {"t", 1}], 2) = 1025
readv(3, [{"", 0}, {"ys to the keyserver.\n\n#keyserver"..., 1024}], 2) = 1024
writev(4, [{"o increase the amount\n#         "..., 1024}, {"I", 1}], 2) = 1025
readv(3, [{"", 0}, {"c OS X and Windows, the default "..., 1024}], 2) = 413
writev(4, [{"Ds in key listings and\n# when a "..., 1024}, {"t", 1}], 2) = 1025
readv(3, [{"", 0}, {"c OS X and Windows, the default "..., 1024}], 2) = 0
writev(4, [{"o-viewer \"qiv %i\"\n# photo-viewer"..., 307}, {NULL, 0}], 2) = 307
close(4)                                = 0
close(3)                                = 0
write(2, "gpg: new configuration file '/ro"..., 50gpg: new configuration file '/root/.gnupg/gpg.conf) = 50
write(2, "' created\n", 10' created
)             = 10
write(2, "gpg: WARNING: options in '/root/"..., 38gpg: WARNING: options in '/root/.gnupg) = 38
write(2, "' are not yet active during this"..., 37' are not yet active during this run
) = 37
access("/root/.gnupg", F_OK)            = 0
getpid()                                = 17
uname({sysname="Linux", nodename="60fbb80a7ebb", ...}) = 0
getpid()                                = 17
open("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", O_WRONLY|O_CREAT|O_EXCL, 0644) = 3
write(3, "        17\n", 11)            = 11
write(3, "60fbb80a7ebb", 12)            = 12
write(3, "\n", 1)                       = 1
close(3)                                = 0
stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0
link("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", "/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17x") = 0
stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0
unlink("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17x") = 0
link("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", "/root/.gnupg/pubring.kbx.lock") = 0
stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0
access("/root/.gnupg/pubring.kbx", F_OK) = -1 ENOENT (No such file or directory)
umask(077)                              = 022
open("/root/.gnupg/pubring.kbx", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
brk(0)                                  = 0x7f7528fc5000
brk(0x7f7528fc8000)                     = 0x7f7528fc8000
umask(022)                              = 077
close(3)                                = 0
open("/root/.gnupg/pubring.kbx", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
ioctl(3, TIOCGWINSZ, 0x7fff3556c968)    = -1 ENOTTY (Not a tty)
writev(3, [{"\0\0\0 \1\1\0\2KBXf\0\0\0\0W\30+\243W\30+\243\0\0\0\0\0\0\0\0", 32}, {NULL, 0}], 2) = 32
close(3)                                = 0
write(2, "gpg: keybox '/root/.gnupg/pubrin"..., 37gpg: keybox '/root/.gnupg/pubring.kbx) = 37
write(2, "' created\n", 10' created
)             = 10
open("/root/.gnupg/pubring.kbx.lock", O_RDONLY) = 3
read(3, "        17\n60fbb80a7ebb\n", 24) = 24
close(3)                                = 0
getpid()                                = 17
unlink("/root/.gnupg/pubring.kbx.lock") = 0
unlink("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17") = 0
access("/root/.gnupg/secring.gpg", F_OK) = -1 ENOENT (No such file or directory)
open("/dev/tty", O_RDWR)                = 3
ioctl(3, TIOCGWINSZ, {ws_row=43, ws_col=174, ws_xpixel=0, ws_ypixel=0}) = 0
writev(3, [{"Note: Use \"gpg2 --full-gen-key", 30}, {"\" for a full featured key genera"..., 45}], 2Note: Use "gpg2 --full-gen-key" for a full featured key generation dialog.
) = 75
writev(3, [{"", 0}, {"\nGnuPG needs to construct a user"..., 59}], 2
GnuPG needs to construct a user ID to identify your key.

) = 59
writev(3, [{"Real name: ", 11}, {NULL, 0}], 2Real name: ) = 11
read(3,
  • Try running strace -f gpg --gen-key and see if there's a call failing with ENOENT just before the “No such file or directory” message. – Gilles Apr 18 '16 at 21:42
  • For info I reported the issue here: bugs.alpinelinux.org/issues/5594 – Antoine Cotten May 18 '16 at 18:50
4

The problem seems to be related to pinentry and the tty. The same command works perfectly with Ubuntu. tty in a Alpine Linux container displays /0 while tty in a Ubuntu container shows /dev/console

By first exporting a correct tty for gpg (export GPG_TTY=/dev/console) the command works and shows the password dialog.

  • 1
    I had a similar problem after a su - $user (from root) - logging in properly with a password gave $(tty) correct permissions crw------- so gpg key generation worked – Stuart Cardall Apr 14 '17 at 23:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.