GithubHelp home page GithubHelp logo

pikvm / pi-builder Goto Github PK

View Code? Open in Web Editor NEW
92.0 10.0 57.0 14.78 MB

Extensible tool to build Arch Linux ARM for Raspberry Pi on x86_64 host using Docker

Home Page: https://pikvm.org

License: GNU General Public License v3.0

Makefile 43.72% Shell 1.42% Python 53.68% C 1.18%
docker builder build-tool build-system build-environment raspberry-pi raspberrypi makefile arm binfmt-misc

pi-builder's Introduction

pi-builder

pi-builder is an easy-to-use and extendable tool to build Arch Linux ARM for Raspberry Pi using Docker.


Challenge

To build an OS, developers usually use a set of shell scripts, unique for each distribution. Those scripts create a chroot with necessary packages, edit configs, add users and so on. As a result, the system has the bare minimum to load, run and be further customised by the user.

However, when you create a product based on a single-board machine (a small router, an IP-camera, a smart home controller, etc), you might want to log all changes you made to the fresh OS to be able to repeat them without forgetting an important step like setting up sysctl.

A common solution is to create a large and horrifying shell script that executes all necessary actions either on the dev machine or the device itself. In case you use chroot and binfmt_misc or need to save intermediate changes, script complexity grows exponentially and it quickly becomes impossible to support.


What is pi-builder?

It's a new approach to target OS building on embedded devices. With pi-builder, you can build an image as if it was a simple Docker container rather than a real-world device OS. The build process is described using the default docker file syntax and it's executed in Docker on your dev machine. The resulting image can be exported to the SD card and loaded directly to Raspberry Pi.


Why pi-builder?

  • Builds are documented and repeatable. A docker file is virtually ready documentation listing steps needed to set up the whole system.
  • Simplicity. Seriously, what can be easier than writing a docker file?
  • Speed and build caching. Target OS building can consist of hundreds of complicated and long steps. Thanks to Docker and its caching you won't run all of them each time you build a new OS; execution will start from whatever command was changed, taking previous results from cache.
  • Real environment testing. When you're developing software that will run on Raspberry Pi it makes sense to test it using the same environment to avoid future problems.

How does it work?

Arch Linux ARM (and other systems as well) comes in form of a minimal root file system you can install on and run from a flash drive. As those are regular roots, you can use them to create your own base Docker image using FROM scratch. This image, however, will contain executables and libraries for the ARM architecture, and if your machine is, eg., x86_64, none of the commands in this image will run.

The Linux kernel, however, has a special way to run binaries on a different architecture. You can configure binfmt_misc to run ARM binaries using an emulator (in this case, qemu-arm-static for x86_64 ). Pi-builder has a small script that sets up binfmt_misc on the host system to run ARM files.

In pi-builder, OS building is separated into stages, each of them being a different element of OS configuration. For example, the ro stage includes Dockerfile.part with all the necessary instructions and configs to create a read-only root. A watchdog stage has everything needed to set up a watchdog with optimal parameters on Raspberry Pi.

A full list of stages that come with pi-builder can be found here or below. You can choose the stages you need to set up your system and include them in your config. Stages are basically pieces of docker file that are combined in a specific order and executed during the build. You can also create your own stages by analogy.

Build sequence:

  1. pi-builder downloads statically compiled Debian qemu-arm-static and sets up binfmt_misc globally on your machine.
  2. The Arch Linux ARM image is downloaded and loaded into Docker as a base image.
  3. The container is build using the necessary stages -- package installation, configuration, cleanup, etc.
  4. You can run docker run (or make shell) in the resulting container to make sure everything's fine.
  5. Pi-builder's utility docker-extract extracts the container from Docker's internal storage and moves to the directory, making it an ordinary root file system.
  6. You can copy the resulting file system to the SD card and use it to load Raspberry Pi.

Usage

To build with pi-builder you need a fresh Docker that can run privileged containers (needed by auxilary image to install binfmt_misc, format the SD card and some other operations).

Pi-builder is configured by the main Makefile in the repository root. You can change parameters in the beginning, to do so create a file config.mk with new values. Default values are:

# Temporary images namespace, call in whatever you like
PROJECT ?= common

# Target Raspberry Pi platform
BOARD ?= rpi4

# List of necessary stages, more on it below
STAGES ?= __init__ os pikvm-repo watchdog no-bluetooth no-audit ro ssh-keygen __cleanup__

# Target system hostname
HOSTNAME ?= pi

# Target system locale (UTF-8)
LOCALE ?= en_US

# Target system timezone
TIMEZONE ?= Europe/Moscow

# Memory card location
CARD ?= /dev/mmcblk0

The most important parameters are BOARD (which board should the system be built for), STAGES (which stages should be included) and CARD (the SD card directory). You can change them by either passing new parameters when you run make, or by creating a config.mk with new values.

The __init__ stage must always be first: it has init instructions to create the base system image (FROM scratch). Stages that follow make the system "feel like home" -- by installing useful packages, setting up watchdog, making the system read-only, setting up root SSH keys and cleaning up temp files.

You can create your own stages and add them to the build alongside stock ones. To do so, create a directory for your stage in the stages folder and place the Dockerfile.part file there, similar to other stages. Alternatively, you can follow the same path as Pi-KVM (which was the first project pi-builder was made for).


Stock stages

  • __init__ - the main stage that creates the base image based on root FS Arch Linux ARM. It should ALWAYS come first in the STAGES list.
  • os - installs some packages and sets the system up a bit to make it more comfortable. You can check what's inside.
  • ro - makes the system a read-only OS. When run like this, you can simply unplug Raspberry Pi without shutting it down properly, without the risk of corrupting the file system. To temporary make the system writable (eg., to install updates), use the rw command. After applying all changes, run ro again to remount the system as read-only.
  • pikvm-repo - adds the key and the Pi-KVM repo. It's needed for the watchdog, but it has other useful packages too. You can skip this stage.
  • watchdog - sets up the hardware watchdog.
  • no-bluetooth - disables the Bluetooth device and restores UART0/ttyAMA0 to GPIOs 14 and 15.
  • no-audit - disables Kernel audit.
  • ssh-root - removes the alarm user, blocks the root password and and keys from stages/ssh-root/pubkeys to the ~/.ssh/authorized_keys. This directory contains pi-builder dev's keys by default, make sure to change them! This stage also disables UART login. In case you need it, you can create your own stage with similar functions.
  • ssh-keygen - generates host SSH keys. The system will ALWAYS be rebuilt on this stage. You don't usually need manual key generation, but in case the system is loaded as read-only, SSH can't generate its own keys on startup.
  • __cleanup__ - cleans up temporary directories after build.

Limitations


Some files, like /etc/host and /etc/hostname, are automatically filled by docker and all changes made from the docker file will be lost. For the hostname, there is a hack in the Makefile that writes the hostname to the exported system, or sets this name on make run. So in case you need to change something in those files, add it to the Makefile in a similar way.


TL;DR

How to build a system for Raspberry Pi 4 and install it to the SD card:

$ git clone https://github.com/pikvm/pi-builder
$ cd pi-builder
$ make rpi4
$ make install

How to build a system with your own stage list:

$ make os BOARD=rpi4 STAGES="__init__ os __cleanup__"

You can see other commands and current build config like so:

$ make

===== Available commands  =====
    make                # Print this help
    rpi2|rpi3|rpi4|zero2w  # Build Arch-ARM rootfs with pre-defined config
    make shell          # Run Arch-ARM shell
    make binfmt         # Before build
    make scan           # Find all RPi devices in the local network
    make clean          # Remove the generated rootfs
    make install         # Format /dev/mmcblk0 and flash the filesystem

===== Running configuration =====
    PROJECT = common
    BOARD   = rpi4
    STAGES  = __init__ os watchdog no-bluetooth ro ssh-keygen __cleanup__

    BUILD_OPTS =
    HOSTNAME   = pi
    LOCALE     = en_US
    TIMEZONE   = Europe/Moscow

    CARD = /dev/mmcblk0

    QEMU_RM     = 1
  • Important: Make sure the SD card directory is in the CARD variable in the Makefile and automount is turned off, or else the newly formatted SD card will be mounted to your system and the setup script will fail.
  • Very important: Make sure your SSH key is in the stages/arch/ssh-root/pubkeys directory, or else you won't be able to log in to your system. Alternatively, don't use the ssh-root stage.
  • Most important: Make sure to read the whole README to understand what you're doing.

License

Copyright (C) 2018-2023 by Maxim Devaev [email protected]

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

pi-builder's People

Contributors

alansill avatar bbeaudoin avatar etkaar avatar faddat avatar goblinqueen avatar intelfx avatar jakicoll avatar lopromise avatar mdevaev avatar msumulong avatar reedy avatar squoimote avatar xornet-sl avatar yura80 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pi-builder's Issues

error: failed to initialize alpm library

I cloned the repo, dropped the example config.mk in, and get the below result. I originally hit this issue while using pikvm to build a pi zero image.

And I have attempted to build this on several computers all running Ubuntu 20.04.

ubuntu@UbuntuDev:~/pi-builder$ make rpi3
===== Ensuring toolbox image =====
docker build
--rm
--tag pi-builder-arm-toolbox

--file toolbox/Dockerfile.root
toolbox
Sending build context to Docker daemon 15.36kB
Step 1/6 : FROM archlinux/archlinux:base-devel
---> bb1d16ed17e2
Step 2/6 : RUN mkdir -p /etc/pacman.d/hooks && ln -s /dev/null /etc/pacman.d /hooks/30-systemd-tmpfiles.hook
---> Using cache
---> 1ef62ba9ddd3
Step 3/6 : RUN pacman --noconfirm -Syu && pacman --needed --noconfirm -S a rp-scan python parted dosfstools r sync && (pacman --noconfirm -Sc || true) && rm -rf /var/cache/pacman/pkg/ *
---> Running in 9446a1e948e0
error: failed to initialize alpm library
(could not find or read directory: /var/lib/pacman/)
The command '/bin/sh -c pacman --noconfirm -Syu && pacman --needed --noc onfirm -S arp-scan python parted d osfstools rsync && (pacman --noconfirm -Sc || true) && rm -r f /var/cache/pacman/pkg/*' returned a non-zero code: 255
make: *** [Makefile:197: toolbox] Error 255

Running on Ubuntu 20.04 with the latest docker-ce.

[Essay of sorts] Commentary on Pi Image Generation

Hey so for some time I have been working on raspberry pi image generation.

Probably what I end up doing with pi-builder looks more like a fork or use of your design pattern.

I guess that one of the things that I'm looking for here is criticism of my proposed architecture because obviously you have spent a lot of time on this as well.

So far I have been using packer-builder-arm. Everything that would happen inside the darker container here happens inside a chroot over there.

The chroot doesn't allow for some things, like systemctl enable, and if you're using ubuntu, apt upgrade, If that upgrade will trigger kernel changes.

With pi-builder, what I found is that there's probably too many options although I think that this is the closest to ideal solution that I found by a wide margin. So what I'm going to do is I am going to take all of the Dockerfile.part files and make them into one Dockerfile. There are a number of reasons for this but probably the biggest one is that this will be fed into a code generator and spent out the other side and I think it's going to end up being a lot easier to manage as a single Dockerfile, single Makefile and a folder of dependencies.

I could be wrong and that's part of why am making this issue actually. I think that this is a really badly needed product. Currently it's much too hard to create images for embedded devices. It's that difficulty that actually drove me to try and bundle this into starport, our blockchain scaffolding tool.

I might break this out into an independent repository as kind of like a framework similar to pi builder but with fewer options and only in a 64-bit mode.

Ideally, I'd like my tool to be totally separate from the app that runs on top of it.

I just wanted to say thanks so much for your work, there are a lot of things in here that I had been having a difficult time figuring out and I'm just delighted that you made this open source and allowed me to learn from it. I'll link you to what I come up with later tonight. So far it's just been some basic customization and toying around but I think that in the next eight hours or so I'll actually have my setup in a pretty decent spot, owing in large part to your work.

Cheers!
-Jacob

Build Fails in Podman using non-Root

Running on an updated Fedora 33

$ uname -a
Linux localhost.localdomain 5.9.13-200.fc33.x86_64 #1 SMP Tue Dec 8 15:42:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Using alias to podman,

$ ls -lsa `which docker`
0 lrwxrwxrwx. 1 root root 15 Dec 10 18:49 /usr/bin/docker -> /usr/bin/podman

$ podman --version
podman version 2.2.1

As non-root use, I can access /tools/install-binfmt

$ ls /proc/sys/fs/binfmt_misc/
arm  register  status

During a build of PiKVM (make os), Podman is unable to mount:

===== Toolbox image is ready =====
===== Ensuring arm binfmt =====
docker run \
		--rm \
		--tty \
		--privileged \
	pi-builder-toolbox /tools/install-binfmt \
		--mount \
		arm \
		/usr/bin/qemu-arm-static
:: Mounting binfmt_misc to '/proc/sys/fs/binfmt_misc' ...
mount: /proc/sys/fs/binfmt_misc: permission denied.
Traceback (most recent call last):
  File "/tools/install-binfmt", line 139, in <module>
    main()
  File "/tools/install-binfmt", line 128, in main
    _mount_binfmt(options.binfmt_misc)
  File "/tools/install-binfmt", line 68, in _mount_binfmt
    subprocess.check_output(["mount", "binfmt_misc", "-t", "binfmt_misc", mount_path])
  File "/usr/lib/python3.9/subprocess.py", line 420, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.9/subprocess.py", line 524, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['mount', 'binfmt_misc', '-t', 'binfmt_misc', '/proc/sys/fs/binfmt_misc']' returned non-zero exit status 32.
make[1]: *** [Makefile:186: binfmt] Error 1
make[1]: Leaving directory '/home/cduplantis/code/pikv/os/.pi-builder'
make: *** [Makefile:54: os] Error 2

This is successful with sudo/rooted user however.

Potentially related to containers/podman#4725

"404 Not Found" when trying to build - ArchLinux naming scheme changed

I'm trying to build PiKVM for my Raspberry Pi 3.
But the following error shows up:

...
===== Binfmt arm is ready =====
===== Ensuring base rootfs =====
if [ ! -e ./.cache/base-rootfs-rpi3.tar.gz ]; then \
        mkdir -p ./.cache \
        && echo "Signature: 8a477f597d28d172789f06886806bc55" > "./.cache/CACHEDIR.TAG" \
        && curl -L -f http://de3.mirror.archlinuxarm.org/os/ArchLinuxARM-rpi-2-latest.tar.gz -z ./.cache/base-rootfs-rpi3.tar.gz -o ./.cache/base-rootfs-rpi3.tar.gz \
; fi
Warning: Illegal date format for -z, --time-cond (and not a file name).
Warning: Disabling time condition. See curl_getdate(3) for valid date syntax.
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (22) The requested URL returned error: 404 Not Found
make[1]: *** [Makefile:277: _rpi_base_rootfs_tgz] Error 22

The URL to the Arch image (in this case http://de3.mirror.archlinuxarm.org/os/ArchLinuxARM-rpi-2-latest.tar.gz) is not available anymore. I think they may have changed their naming-scheme.

If i'm correct then http://de3.mirror.archlinuxarm.org/os/ArchLinuxARM-rpi-aarch64-latest.tar.gz should be the right image for the Raspi3.

I believe that this just needs a simple fix in the Makefile.

Producing a .img file instead of flashing

I am testing out this system for use in Starport, a rapid blockchain development tool that allows developers and entrepreneurs to ship blockchain products as hardware.

I am trying to figure out if there is a way to get output as an image file.

Currently, I have been using packer-builder-arm but the docker-based approach used here looks interesting.

Goal

Basically, I just need to know how to build an image file instead of flashing to SD card, and we could use pi-builder and significantly lower our build times and increase development speed by reducing the length of CI cycles.

Trying to make os for Pi Zero W

Hello,
I've tried many times to get pikvm to get past the "make os" step but I always get the below output, it looks to trying to get the image from a URL that no longer exists.

===== Ensuring base rootfs =====
if [ ! -e ./.cache/base-rootfs-zerow.tar.gz ]; then
mkdir -p ./.cache
&& echo "Signature: 8a477f597d28d172789f06886806bc55" > "./.cache/CACHEDIR.TAG"
&& curl -L -f http://de3.mirror.archlinuxarm.org/os/ArchLinuxARM-rpi-latest.tar.gz -z ./.cache/base-rootfs-zerow.tar.gz -o ./.cache/base-rootfs-zerow.tar.gz
; fi
Warning: Illegal date format for -z, --time-cond (and not a file name).
Warning: Disabling time condition. See curl_getdate(3) for valid date syntax.
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (22) The requested URL returned error: 404 Not Found
make[1]: *** [Makefile:276: _rpi_base_rootfs_tgz] Error 22
make[1]: Leaving directory '/home/shawn/os/.pi-builder/v2-hdmi-zerow'
make: *** [Makefile:52: os] Error 2

Try to use it pi-builder with raspberry pi os

I'am customizing pi-builder to build raspberry pi os instead of arch.
Currently I'am doing this in the makefile:

_rpi_base_rootfs_tgz: # 3rd step in make - downloads base root fs as tgz file not an image
	$(call say,"Ensuring base rootfs")
	if [ ! -e $(_RPI_BASE_ROOTFS_TGZ) ]; then \
		mkdir -p $(_CACHE_DIR) \
		&& cd $(_CACHE_DIR) \
		&& curl -L -f $(_RPI_ROOTFS_URL) -o $(_PIOS_IMAGE_NAME) \
		&& unxz -f $(_PIOS_IMAGE_NAME) \
		&& 7z x -aoa pi_image.img 1.img \
		&& mkdir -p root_fs \
		&& cd root_fs \
		&& 7z x -aoa ../1.img \
		&& rm -rf lib \
		&& ln -s usr/lib lib \
		&& cd ../.. \
		&& chmod -R +x .cache/root_fs/usr/bin/bash \
		&& cd .cache/root_fs \
		&& tar -czf ../.$(_RPI_BASE_ROOTFS_TGZ) * \
		&& echo "Signature: 8a477f597d28d172789f06886806bc55" > "../.$(_CACHE_DIR)/CACHEDIR.TAG" \
	; fi

But during OS building I hit a wall with:

qemu-arm-static: /lib/ld-linux-armhf.so.3: Invalid ELF image for this architecture

Dockerfile inside .build looks like this:

FROM scratch

ADD "common-pi-builder-arm-base-rootfs-rpi4.tgz" /
COPY "qemu-arm-static-orig" "/usr/bin/qemu-arm-static-orig"
COPY "qemu-arm-static" "/usr/bin/qemu-arm-static"
#RUN mkdir -p /etc/pacman.d/hooks \
#	&& ln -s /dev/null /etc/pacman.d/hooks/30-systemd-tmpfiles.hook

ARG BOARD
ENV BOARD $BOARD

ARG ARCH
ENV ARCH $ARCH

ARG LOCALE
ENV LOCALE $LOCALE

ARG TIMEZONE
ENV TIMEZONE $TIMEZONE

ARG REPO_URL
ENV REPO_URL $REPO_URL

ARG PIKVM_REPO_URL
ENV PIKVM_REPO_URL $PIKVM_REPO_URL

ARG PIKVM_REPO_KEY
ENV PIKVM_REPO_KEY $PIKVM_REPO_KEY
# https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg03681.html
SHELL ["/usr/bin/bash"]


RUN echo "foobar---------------------"

The error messages appears when I try to run an echo in the last line.

error: target not found: openssl-1.0

I'm trying to build PiKVM for my Raspberry Pi 3.
But the following error shows up:

Step 2/7 : RUN mkdir -p /etc/pacman.d/hooks 	&& ln -s /dev/null /etc/pacman.d/hooks/30-systemd-tmpfiles.hook
 ---> Running in 4fbcda98e049
Removing intermediate container 4fbcda98e049
 ---> b0d8d04fe8f2
Step 3/7 : RUN pacman --noconfirm --ask=4 -Syy 	&& pacman --needed --noconfirm --ask=4 -S 		glibc 		openssl 		openssl-1.0 		openssl-1.1 	&& pacman --needed --noconfirm --ask=4 -S 		pacman 	&& pacman-db-upgrade 	&& pacman-key --init 	&& pacman --needed --noconfirm --ask=4 -S 		p11-kit 		archlinux-keyring 		ca-certificates 		ca-certificates-mozilla 		ca-certificates-utils 	&& pacman --noconfirm --ask=4 -Syu 	&& pacman --needed --noconfirm --ask=4 -S 		arp-scan 		python 		parted 		dosfstools 		rsync 	&& rm -rf /var/cache/pacman/pkg/*
 ---> Running in 6be9e605b91a
:: Synchronizing package databases...
 core downloading...
 extra downloading...
 community downloading...
warning: glibc-2.36-6 is up to date -- skipping
warning: openssl-3.0.7-4 is up to date -- skipping
error: target not found: openssl-1.0

I've removed manually openssl-1.0 and everything rest was correct

I believe that this just needs a simple fix in the os stage dockerfile .

pacman-key --populate fails because current time is not accessible in the build container

I'm trying to make os BOARD=rpi STAGES="__init__ os __cleanup__".

It fails at the pacman-key --populate archlinuxarm step:

Step 22/42 : RUN echo "Server = $REPO_URL/$arch/$repo" > /etc/pacman.d/mirrorlist && pacman-key --init && pacman-key --populate archlinuxarm
[...]
==> Appending keys from archlinuxarm.gpg...
gpg: key B55C5315DCD9EE1A was created 16088 days in the future (time warp or clock problem)

So I got a shell in the intermediate build container and found:

[root@d5d472cce578 /]# date
Thu 01 Jan 1970 03:00:00 AM MSK

While in the toolbox, things are fine:

$ docker run -it pi-builder-arm-toolbox
[root@c93584cae3b0 /]# date
Wed Dec 30 04:52:35 PM UTC 2020

I'll try to investigate further, but thought I'd let you know at this point. :)

Thank you for this bright idea on how to automate building these images. I'm currently evaluation different ways and this looks very promising. ๐Ÿ‘

docker-extract

JSON Parse issue

But the thing is I haven't been able to figure out what is different about these two images as compared to the other ones.

I'll keep looking into it :)

Possible solutions?

Dirmngr issue with systemd-resolved

Docker does not work perfectly with systemd-resolved and dirmngr seems to suffer from this.

PR #15 submitted to fix this issue.

[root@62cd68d26d6f pacman.d]# pacman-key --keyserver hkps://hkps.pool.sks-keyservers.net -r 912C773ABBD1B584
gpg: keyserver receive failed: Server indicated a failure
==> ERROR: Remote key not fetched correctly from keyserver.
[root@62cd68d26d6f pacman.d]# echo standard-resolver >> /etc/gnupg/dirmngr.conf
[root@62cd68d26d6f pacman.d]# killall dirmngr
[root@62cd68d26d6f pacman.d]# pacman-key --keyserver hkps://hkps.pool.sks-keyservers.net -r 912C773ABBD1B584
gpg: key 912C773ABBD1B584: "Maxim Devaev <[email protected]>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
[root@62cd68d26d6f pacman.d]#

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.