diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0fa7348 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +* +!archlinux.tar +!archlinux.tar.xz diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 9d120d3..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Github-Actions - -on: [push, pull_request] - -jobs: - ci-test: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: make ci-test - run: make ci-test diff --git a/.gitignore b/.gitignore index e573ef4..6a9306a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ *.orig /.idea /archlinux.tar +/archlinux.tar.xz rootfs/etc/pacman.conf diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..eed2256 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,50 @@ +stages: + - rootfs + - docker + - test + +roofs: + stage: rootfs + image: archlinux:latest + script: + - pacman -Syu --noconfirm make devtools fakechroot fakeroot + - make compress-rootfs + artifacts: + paths: + - archlinux.tar.xz + expire_in: 10m + +docker: + stage: docker + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - test -f archlinux.tar.xz + # kaniko can't process .tar.xz archives + # https://github.com/GoogleContainerTools/kaniko/issues/1107 + - unxz archlinux.tar.xz + - test -f archlinux.tar + - sed -i 's/archlinux\.tar\.xz/archlinux\.tar/g' Dockerfile + - echo "Building ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}" + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + - /kaniko/executor + --whitelist-var-run="false" + --context $CI_PROJECT_DIR + --dockerfile $CI_PROJECT_DIR/Dockerfile + --destination ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG} + +test: + stage: test + image: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG} + needs: + - job: docker + artifacts: false + script: + - pacman -Sy + - pacman -Qqk + - pacman -Syu --noconfirm docker grep + - docker -v + - id -u http + - locale | grep -q UTF-8 + diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index cfc4d72..0000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -sudo: required - -language: bash - -services: - - docker - -script: - - make ci-test diff --git a/Dockerfile b/Dockerfile index cde2238..02fbabc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,15 @@ FROM scratch -ADD archlinux.tar / +ADD archlinux.tar.xz / + +# manually run all alpm hooks that can't be run inside the fakechroot +RUN ldconfig && update-ca-trust && locale-gen +RUN sh -c 'ls usr/lib/sysusers.d/*.conf | /usr/share/libalpm/scripts/systemd-hook sysusers ' + +# update /etc/os-release +RUN ln -s /usr/lib/os-release /etc/os-release + +# initialize the archlinux keyring, but discard any private key that may be shipped. +RUN pacman-key --init && pacman-key --populate archlinux && rm -rf etc/pacman.d/gnupg/{openpgp-revocs.d/,private-keys-v1.d/,pubring.gpg~,gnupg.S.}* + ENV LANG=en_US.UTF-8 CMD ["/usr/bin/bash"] diff --git a/Makefile b/Makefile index 32619f5..61fb0db 100644 --- a/Makefile +++ b/Makefile @@ -1,38 +1,52 @@ DOCKER_USER:=pierres DOCKER_ORGANIZATION=archlinux DOCKER_IMAGE:=base +BUILDDIR=build +PWD=$(shell pwd) -rootfs: - $(eval TMPDIR := $(shell mktemp -d)) +XZ_THREADS ?= 0 + +hooks: + mkdir -p alpm-hooks/usr/share/libalpm/hooks + find /usr/share/libalpm/hooks -exec ln -sf /dev/null $(PWD)/alpm-hooks{} \; + +rootfs: hooks + mkdir -vp $(BUILDDIR)/var/lib/pacman/ cp /usr/share/devtools/pacman-extra.conf rootfs/etc/pacman.conf cat pacman-conf.d-noextract.conf >> rootfs/etc/pacman.conf - env -i pacstrap -C rootfs/etc/pacman.conf -c -d -G -M $(TMPDIR) $(shell cat packages) - cp --recursive --preserve=timestamps --backup --suffix=.pacnew rootfs/* $(TMPDIR)/ - arch-chroot $(TMPDIR) locale-gen - arch-chroot $(TMPDIR) pacman-key --init - arch-chroot $(TMPDIR) pacman-key --populate archlinux - tar --numeric-owner --xattrs --acls --exclude-from=exclude -C $(TMPDIR) -c . -f archlinux.tar - rm -rf $(TMPDIR) + fakechroot -- fakeroot -- pacman -Sy -r $(BUILDDIR) \ + --noconfirm --dbpath $(PWD)/$(BUILDDIR)/var/lib/pacman \ + --config rootfs/etc/pacman.conf \ + --noscriptlet \ + --hookdir $(PWD)/alpm-hooks/usr/share/libalpm/hooks/ $(shell cat packages) + cp --recursive --preserve=timestamps --backup --suffix=.pacnew rootfs/* $(BUILDDIR)/ + + # remove passwordless login for root (see CVE-2019-5021 for reference) + sed -i -e 's/^root::/root:!:/' "$(BUILDDIR)/etc/shadow" -docker-image: rootfs + # fakeroot to map the gid/uid of the builder process to root + # fixes #22 + fakeroot -- tar --numeric-owner --xattrs --acls --exclude-from=exclude -C $(BUILDDIR) -c . -f archlinux.tar + rm -rf $(BUILDDIR) alpm-hooks + +archlinux.tar: rootfs + +compress-rootfs: archlinux.tar + xz -9 -T"$(XZ_THREADS)" -f archlinux.tar + +docker-image: compress-rootfs docker build -t $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) . docker-image-test: docker-image # FIXME: /etc/mtab is hidden by docker so the stricter -Qkk fails docker run --rm $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) sh -c "/usr/bin/pacman -Sy && /usr/bin/pacman -Qqk" - docker run --rm $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) sh -c "/usr/bin/pacman -Syu --noconfirm docker && docker -v" - # Ensure that the image does not include a private key + docker run --rm $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) sh -c "/usr/bin/pacman -Syu --noconfirm docker && docker -v" # Ensure that the image does not include a private key ! docker run --rm $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) pacman-key --lsign-key pierre@archlinux.de docker run --rm $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) sh -c "/usr/bin/id -u http" docker run --rm $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) sh -c "/usr/bin/pacman -Syu --noconfirm grep && locale | grep -q UTF-8" -ci-test: - docker run --rm --privileged --tmpfs=/tmp:exec --tmpfs=/run/shm -v /run/docker.sock:/run/docker.sock \ - -v $(PWD):/app -w /app $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) \ - sh -c 'pacman -Syu --noconfirm make devtools docker && make docker-image-test' - docker-push: docker login -u $(DOCKER_USER) docker push $(DOCKER_ORGANIZATION)/$(DOCKER_IMAGE) -.PHONY: rootfs docker-image docker-image-test ci-test docker-push +.PHONY: rootfs docker-image docker-image-test docker-push diff --git a/README.md b/README.md index 4dfbc53..8e80316 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ Install the following Arch Linux packages: * make * devtools * docker +* fakechroot +* fakeroot ## Usage Run `make docker-image` as root to build the base image. ## Purpose diff --git a/exclude b/exclude index 1517525..0a45d22 100644 --- a/exclude +++ b/exclude @@ -1,13 +1,16 @@ -.dockerenv -.dockerinit -etc/hostname -etc/machine-id -etc/pacman.d/gnupg/openpgp-revocs.d/* -etc/pacman.d/gnupg/private-keys-v1.d/* -etc/pacman.d/gnupg/pubring.gpg~ -etc/pacman.d/gnupg/S.* -root/* -tmp/* -var/cache/pacman/pkg/* -var/lib/pacman/sync/* -var/tmp/* +./.dockerenv +./.dockerinit +./sys +./proc +./dev +./etc/hostname +./etc/machine-id +./etc/pacman.d/gnupg/openpgp-revocs.d/* +./etc/pacman.d/gnupg/private-keys-v1.d/* +./etc/pacman.d/gnupg/pubring.gpg~ +./etc/pacman.d/gnupg/S.* +./root/* +./tmp/* +./var/cache/pacman/pkg/* +./var/lib/pacman/sync/* +./var/tmp/* \ No newline at end of file diff --git a/packages b/packages index 39dffd0..2c07590 100644 --- a/packages +++ b/packages @@ -2,3 +2,9 @@ sed gzip pacman systemd +gawk +file +grep +tar +procps-ng +licenses diff --git a/pacman.conf b/pacman.conf new file mode 100644 index 0000000..4cf98ed --- /dev/null +++ b/pacman.conf @@ -0,0 +1,91 @@ +# +# /etc/pacman.conf +# +# See the pacman.conf(5) manpage for option and repository directives + +# +# GENERAL OPTIONS +# +[options] +# The following paths are commented out with their default values listed. +# If you wish to use different paths, uncomment and update the paths. +#RootDir = / +#DBPath = /var/lib/pacman/ +#CacheDir = /var/cache/pacman/pkg/ +#LogFile = /var/log/pacman.log +#GPGDir = /etc/pacman.d/gnupg/ +#HookDir = /etc/pacman.d/hooks/ +#HoldPkg = pacman glibc +#XferCommand = /usr/bin/curl -C - -f %u > %o +#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u +#CleanMethod = KeepInstalled +#UseDelta = 0.7 +Architecture = auto + +# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup +#IgnorePkg = +#IgnoreGroup = + +#NoUpgrade = +#NoExtract = + +# Misc options +#UseSyslog +#Color +#TotalDownload +CheckSpace +#VerbosePkgLists + +# By default, pacman accepts packages signed by keys that its local keyring +# trusts (see pacman-key and its man page), as well as unsigned packages. +SigLevel = Required DatabaseOptional +LocalFileSigLevel = Optional +#RemoteFileSigLevel = Required + +# NOTE: You must run `pacman-key --init` before first using pacman; the local +# keyring can then be populated with the keys of all official Arch Linux +# packagers with `pacman-key --populate archlinux`. + +# +# REPOSITORIES +# - can be defined here or included from another file +# - pacman will search repositories in the order defined here +# - local/custom mirrors can be added here or in separate files +# - repositories listed first will take precedence when packages +# have identical names, regardless of version number +# - URLs will have $repo replaced by the name of the current repo +# - URLs will have $arch replaced by the name of the architecture +# +# Repository entries are of the format: +# [repo-name] +# Server = ServerName +# Include = IncludePath +# +# The header [repo-name] is crucial - it must be present and +# uncommented to enable the repo. +# + +# The testing repositories are disabled by default. To enable, uncomment the +# repo name header and Include lines. You can add preferred servers immediately +# after the header, and they will be used before the default mirrors. + +[core] +Include = rootfs/etc/pacman.d/mirrorlist + +[extra] +Include = rootfs/etc/pacman.d/mirrorlist + +[community] +Include = rootfs/etc/pacman.d/mirrorlist + +# If you want to run 32 bit applications on your x86_64 system, +# enable the multilib repositories as required here. + +#[multilib] +#Include = /etc/pacman.d/mirrorlist +# +# An example of a custom package repository. See the pacman manpage for +# tips on creating your own repositories. +#[custom] +#SigLevel = Optional TrustAll +#Server = file:///home/custompkgs diff --git a/rootfs/usr/share/libalpm/hooks/package-cleanup.hook b/rootfs/usr/share/libalpm/hooks/package-cleanup.hook deleted file mode 100644 index f5ba631..0000000 --- a/rootfs/usr/share/libalpm/hooks/package-cleanup.hook +++ /dev/null @@ -1,11 +0,0 @@ -[Trigger] -Operation = Install -Operation = Upgrade -Type = Package -Target = * - -[Action] -Description = Cleaning up package cache... -Depends = coreutils -When = PostTransaction -Exec = /usr/bin/find /var/cache/pacman/pkg/ -type f -delete