├── .gitlab-ci.yml ├── Makefile.archlinux ├── Makefile.builder ├── keys ├── archlinux-master-keys.asc ├── qubes-repo-archlinux-key-4.1.asc ├── qubes-repo-archlinux-key-4.2.asc ├── qubes-repo-archlinux-key-4.3.asc └── qubes-repo-archlinux-key.asc ├── prepare-chroot-base ├── prepare-chroot-builder ├── repos ├── archlinux-qubes-repo-4.1-current-testing.conf ├── archlinux-qubes-repo-4.1-current.conf ├── archlinux-qubes-repo-4.2-current-testing.conf ├── archlinux-qubes-repo-4.2-current.conf ├── archlinux-qubes-repo-4.3-current-testing.conf └── archlinux-qubes-repo-4.3-current.conf ├── template_archlinux ├── 00_prepare.sh ├── 01_install_core.sh ├── 02_install_groups.sh ├── 04_install_qubes.sh ├── 09_cleanup.sh ├── appmenus_archlinux │ ├── netvm-whitelisted-appmenus.list │ ├── vm-whitelisted-appmenus.list │ └── whitelisted-appmenus.list ├── appmenus_archlinux_minimal │ ├── netvm-whitelisted-appmenus.list │ ├── vm-whitelisted-appmenus.list │ └── whitelisted-appmenus.list ├── arch-chroot-lite ├── network ├── packages.list ├── packages_minimal.list └── resolv.conf ├── update-local-repo.sh └── update-remote-repo.sh /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: 2 | - project: 'QubesOS/qubes-continuous-integration' 3 | file: '/r4.2/gitlab-base.yml' 4 | - project: 'QubesOS/qubes-continuous-integration' 5 | file: '/r4.2/gitlab-vm-archlinux-build-template.yml' 6 | - project: 'QubesOS/qubes-continuous-integration' 7 | file: '/r4.3/gitlab-base.yml' 8 | - project: 'QubesOS/qubes-continuous-integration' 9 | file: '/r4.3/gitlab-vm-archlinux-build-template.yml' 10 | 11 | default: 12 | tags: 13 | - vm 14 | -------------------------------------------------------------------------------- /Makefile.archlinux: -------------------------------------------------------------------------------- 1 | # Makefile for Archlinux packages build 2 | # 3 | # For "API" documentation check Makefile.generic 4 | # 5 | # Variables supposed to be in component's Makefile.builder: 6 | # ARCH_BUILD_DIRS - list of archlinux directories containing build sripts (PKGFILES...) 7 | 8 | ### Variables required as per Makefile.generic: 9 | # 10 | # PACKAGE_LIST - list of packages to build. Targets 'build-dep', 'package' and 'copy-out' 11 | # will be run for each word on the list, with PACKAGE set to current word 12 | # DIST_BUILD_DIR - basedir for sources inside of chroot - relative to 13 | # CHROOT_DIR (qubes-src will be created in this directory) 14 | # 15 | PACKAGE_LIST = $(ARCH_BUILD_DIRS) 16 | DIST_BUILD_DIR = /home/user 17 | 18 | ### Local variables 19 | RUN_AS_USER = user 20 | 21 | 22 | DEBUG ?= 0 23 | ifneq ($(DEBUG),0) 24 | $(info ╔══ DEBUG ══════════════════════════════════════════════════════════════════════) 25 | $(info ║ Repo Variables) 26 | $(info ╠───────────────────────────────────────────────────────────────────────────────) 27 | $(info ║ SRC_DIR: $(SRC_DIR)) # qubes-src 28 | $(info ║ CHROOT_DIR: $(CHROOT_DIR)) # /home/user/qubes-builder/chroot-archlinux 29 | $(info ║ BUILDER_REPO_DIR: $(BUILDER_REPO_DIR)) # /home/user/qubes-builder/qubes-packages-mirror-repo/archlinux 30 | $(info ╠───────────────────────────────────────────────────────────────────────────────) 31 | $(info ║ Chroot Variables) 32 | $(info ╠───────────────────────────────────────────────────────────────────────────────) 33 | $(info ║ CHROOT_DIR: $(CHROOT_DIR)) # 34 | $(info ║ DIST_BUILD_DIR: $(DIST_BUILD_DIR)) # /home/user 35 | $(info ║ DIST_SRC: $(DIST_SRC)) # /home/user/qubes-src/repo 36 | $(info ╠───────────────────────────────────────────────────────────────────────────────) 37 | $(info ║ Build Variables) 38 | $(info ╠───────────────────────────────────────────────────────────────────────────────) 39 | $(info ║ ARCHLINUX_PLUGIN_DIR: $(ARCHLINUX_PLUGIN_DIR)) # /home/user/qubes-builder/qubes-src/builder-archlinux 40 | $(info ║ CACHEDIR: $(CACHEDIR)) # cache/archlinux 41 | $(info ║ PACKAGE_LIST: $(PACKAGE_LIST)) # archlinux 42 | $(info ║ DISTRIBUTION: $(DISTRIBUTION)) # archlinux 43 | $(info ║ DIST: $(DIST)) # 44 | $(info ║ COMPONENT: $(COMPONENT)) # 45 | $(info ║ PACKAGE_SET: $(PACKAGE_SET)) # vm 46 | $(info ║ CHROOT_ENV: $(CHROOT_ENV)) # BACKEND_VMM=xen 47 | $(info ╠───────────────────────────────────────────────────────────────────────────────) 48 | $(info ║ Repository Variables) 49 | $(info ╠───────────────────────────────────────────────────────────────────────────────) 50 | $(info ║ UPDATE_REPO: $(UPDATE_REPO)) # 51 | $(info ║ TARGET_REPO: $(TARGET_REPO)) # 52 | $(info ║ SNAPSHOT_REPO: $(SNAPSHOT_REPO)) # 53 | $(info ║ SNAPSHOT_FILE: $(SNAPSHOT_FILE)) # 54 | $(info ║ REPO_PROXY: $(REPO_PROXY)) # 55 | $(info ║ ARCHLINUX_SRC_PREFIX: $(ARCHLINUX_SRC_PREFIX)) # http://mirrors.kernel.org/archlinux 56 | $(info ║ ARCHLINUX_REL_VERSION: $(ARCHLINUX_REL_VERSION)) # 57 | $(info ║ ARCHLINUX_MIRROR: $(ARCHLINUX_MIRROR)) # default defined in prepare-chroot-base 58 | $(info ╚═══════════════════════════════════════════════════════════════════════════════) 59 | endif 60 | 61 | define bin_packages 62 | $(shell cd $(ORIG_SRC) && \ 63 | if [ 0`stat -c %Y $(OUTPUT_DIR)/$(notdir $(1)).list 2>/dev/null` -ge \ 64 | 0`git log -1 --pretty=format:%ct` ]; then \ 65 | cat $(OUTPUT_DIR)/$(notdir $(1)).list; \ 66 | else \ 67 | echo unknown.package; \ 68 | fi) 69 | endef 70 | 71 | ### Targets required by Makefile.generic to build packages: 72 | 73 | # dist-prepare-chroot - initial preparation of chroot environment 74 | # Specifically, load mounts for the build chroot 75 | dist-prepare-chroot: $(CHROOT_DIR)/home/user/.prepared_base 76 | @echo "--> Archlinux dist-prepare-chroot (makefile):" 77 | @sudo mkdir -p "$(CACHEDIR)/pacman_cache/pkg" 78 | @sudo touch "$(CACHEDIR)/pacman_cache/pkg/.mnt" 79 | @# qubes pkgs may be from old runs and no longer match the repo hashes 80 | @sudo rm "$(CACHEDIR)/pacman_cache/pkg"/qubes-*.pkg.tar.* 2>/dev/null || true 81 | @mkdir -p "$(BUILDER_REPO_DIR)/pkgs" 82 | @mkdir -p "$(CHROOT_DIR)/var/cache/pacman" 83 | @mkdir -p "$(CHROOT_DIR)/tmp/qubes-packages-mirror-repo" 84 | 85 | # Create the build chroot, if it does not already exist 86 | $(CHROOT_DIR)/home/user/.prepared_base: $(ARCHLINUX_PLUGIN_DIR)/prepare-chroot-builder 87 | @echo "--> Archlinux preparing build chroot environment" 88 | @sudo -E "$(ARCHLINUX_PLUGIN_DIR)/prepare-chroot-builder" "$(CHROOT_DIR)" "$(CACHEDIR)" || exit 1 89 | @touch "$(CHROOT_DIR)/home/user/.prepared_base" 90 | 91 | # dist-prep - some preparation of sources (if needed) 92 | dist-prep: 93 | @true 94 | 95 | # dist-build-dep - install build dependencies (should operate on chroot directory) 96 | dist-build-dep: 97 | @echo "--> Archlinux dist-build-dep (makefile)" 98 | @echo " --> Generate locales..." 99 | @echo "en_US.UTF-8 UTF-8" | sudo tee -a $(CHROOT_DIR)/etc/locale.gen 100 | @sudo $(CHROOT_ENV) chroot "$(CHROOT_DIR)" locale-gen 101 | @echo "LANG=en_US.UTF-8" | sudo tee -a $(CHROOT_DIR)/etc/locale.conf 102 | @sudo -E "$(ARCHLINUX_PLUGIN_DIR)/update-local-repo.sh" $(DIST) 103 | 104 | # dist-package - compile package (should operate on chroot directory) 105 | # TODO: makepkg doesn't seem to honor $http_proxy 106 | dist-package: 107 | @echo "--> Archlinux dist-package (makefile)" 108 | ifndef PACKAGE 109 | $(error "PACKAGE need to be set!") 110 | endif 111 | @echo " --> Building package in $(DIST_SRC)" 112 | sudo systemd-nspawn --directory="$(CHROOT_DIR)" \ 113 | --bind="$(CACHEDIR)/pacman_cache":"/var/cache/pacman" \ 114 | --bind="$(BUILDER_REPO_DIR)":"/tmp/qubes-packages-mirror-repo" \ 115 | --keep-unit \ 116 | --register=no \ 117 | --user=user \ 118 | --setenv=$(CHROOT_ENV) \ 119 | --setenv=SOURCE_DATE_EPOCH="$(shell git -C "$$ORIG_SRC" log -1 --pretty=format:%ct)" \ 120 | --setenv=http_proxy="$(REPO_PROXY)" \ 121 | --chdir="$(DIST_SRC)" \ 122 | sh -c 'if ! [ -e $(PACKAGE)/PKGBUILD.in ]; then cp $(PACKAGE)/PKGBUILD* ./; fi && makepkg --syncdeps --noconfirm --skipinteg' 123 | 124 | # dist-copy-out - copy compiled package out of chroot env; this target should 125 | # move packages to ORIG_SRC (distro-specific subdir) and hardlink them to 126 | # BUILDER_REPO_DIR 127 | dist-copy-out: pkg_list_path = $(ORIG_SRC)/$(OUTPUT_DIR)/$(notdir $(PACKAGE)).list 128 | dist-copy-out: 129 | @echo "--> Archlinux dist-copy-out (makefile)" 130 | @echo "--> Done:" >&3 131 | @set -e;\ 132 | shopt -s nullglob;\ 133 | mkdir -p $(ORIG_SRC)/$(OUTPUT_DIR);\ 134 | echo -n > $(pkg_list_path);\ 135 | for arch_chroot_dir in $(CHROOT_DIR)/$(DIST_SRC)/; do\ 136 | arch_pkg_dir=$(ORIG_SRC)/$(OUTPUT_DIR);\ 137 | mkdir -p $$arch_pkg_dir;\ 138 | for pkg in $$arch_chroot_dir/*.pkg.tar.*; do\ 139 | echo " $$arch_pkg_dir/`basename $$pkg`" >&3 ;\ 140 | echo "$(OUTPUT_DIR)/`basename $$pkg`" >> $(pkg_list_path);\ 141 | done;\ 142 | mkdir -p $(BUILDER_REPO_DIR)/pkgs;\ 143 | ln -f -t $(BUILDER_REPO_DIR)/pkgs $$arch_chroot_dir/*.pkg.tar.*;\ 144 | done;\ 145 | mv -t $$arch_pkg_dir $$arch_chroot_dir/*.pkg.tar.* 146 | 147 | ### Additional targets 148 | 149 | # Sign packages 150 | sign: sign_client = $(if $(GNUPG),$(GNUPG),gpg) 151 | sign: 152 | @if [ -d $(ORIG_SRC)/$(OUTPUT_DIR) ]; then \ 153 | cd $(ORIG_SRC)/$(OUTPUT_DIR); \ 154 | for filename in *.pkg.tar.zst; do\ 155 | echo $$filename; \ 156 | $(sign_client) --yes --local-user "$(ARCHLINUX_SIGN_KEY)" --detach-sign -o "$$filename.sig" "$$filename";\ 157 | ln -f -t $(BUILDER_REPO_DIR)/pkgs "$$filename.sig";\ 158 | done; \ 159 | fi 160 | 161 | 162 | # Copies requested packages (based on PACKAGE_SET, COMPONENT, DIST) to 163 | # requested repository (UPDATE_REPO) 164 | update-repo: 165 | ifndef UPDATE_REPO 166 | $(error "You need to specify destination repo in UPDATE_REPO variable") 167 | endif 168 | ifeq (,$(PACKAGE_LIST)) 169 | @true 170 | else 171 | ifdef SNAPSHOT_FILE 172 | @echo -n > $(SNAPSHOT_FILE) 173 | endif 174 | mkdir -p $(UPDATE_REPO)/pkgs; \ 175 | for package in $(PACKAGE_LIST); do\ 176 | pkgnames=`cat $(ORIG_SRC)/$(OUTPUT_DIR)/$$package.list`;\ 177 | for pkgname in $$pkgnames; do\ 178 | ln -f $(ORIG_SRC)/$$pkgname $(UPDATE_REPO)/pkgs/ || exit 1;\ 179 | ln -f $(ORIG_SRC)/$$pkgname.sig $(UPDATE_REPO)/pkgs/ 2>/dev/null;\ 180 | if [ -n "$(SNAPSHOT_FILE)" ]; then \ 181 | echo $$pkgname >> "$(SNAPSHOT_FILE)"; \ 182 | fi; \ 183 | done; \ 184 | done 185 | endif 186 | 187 | 188 | update-repo-from-snapshot: packages = $(shell cat $(SNAPSHOT_FILE) 2>/dev/null) 189 | update-repo-from-snapshot: 190 | ifndef UPDATE_REPO 191 | $(error "You need to specify destination repo in UPDATE_REPO variable") 192 | endif 193 | mkdir -p $(UPDATE_REPO)/pkgs; \ 194 | for f in $(packages); do \ 195 | ln -f $(subst /$(TARGET_REPO)/,/$(SNAPSHOT_REPO)/,$(UPDATE_REPO)/)pkgs/`basename $$f` $(UPDATE_REPO)/pkgs/ || exit 1; \ 196 | ln -f $(subst /$(TARGET_REPO)/,/$(SNAPSHOT_REPO)/,$(UPDATE_REPO)/)pkgs/`basename $$f`.sig $(UPDATE_REPO)/pkgs/ 2>/dev/null; \ 197 | done 198 | 199 | check-repo: packages = $(foreach pkg,$(PACKAGE_LIST),$(call bin_packages,$(pkg))) 200 | check-repo: 201 | ifndef UPDATE_REPO 202 | $(error "You need to specify destination repo in UPDATE_REPO variable") 203 | endif 204 | @if [ -n "$(strip $(packages))" ]; then \ 205 | cd $(ORIG_SRC) && ls $(addprefix $(UPDATE_REPO)/pkgs/, $(notdir $(packages))) >/dev/null 2>&1 || exit 1; \ 206 | else \ 207 | echo "`tput bold`No packages defined by $(PACKAGE_LIST), syntax error?`tput sgr0`"; \ 208 | exit 1; \ 209 | fi 210 | -------------------------------------------------------------------------------- /Makefile.builder: -------------------------------------------------------------------------------- 1 | ifeq ($(DIST),archlinux) 2 | ARCHLINUX_PLUGIN_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 3 | DISTRIBUTION := archlinux 4 | BUILDER_MAKEFILE = $(ARCHLINUX_PLUGIN_DIR)Makefile.archlinux 5 | TEMPLATE_SCRIPTS = $(ARCHLINUX_PLUGIN_DIR)template_archlinux 6 | endif 7 | 8 | # vim: ft=make 9 | -------------------------------------------------------------------------------- /keys/archlinux-master-keys.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | 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 75 | BQJjX5FXAhsMBQkcMgSAAAoJEHal75BURJpcp2YA/j5YmwE5WqVcc+hKaxjH55LX 76 | r1JX1kMEoUSfsP8fCM8gAP9Jzr6BO4+LHb4OEKFv7Npz2Gg8vBCv1wDEU9eXknGC 77 | B5gzBGNWTu8WCSsGAQQB2kcPAQEHQBx9vvVAF1yV78scJB4+/R5jQ/vn7BR4j2lZ 78 | 6Bn9I0E0tExKb2hhbm5lcyBMw7Z0aGJlcmcgKEFyY2ggTGludXggTWFzdGVyIEtl 79 | eSkgPGRlbWl6ZUBtYXN0ZXIta2V5LmFyY2hsaW51eC5vcmc+iJAEExYKADgWIQRp 80 | 5kceOuBlKXUpgy5roPWiA39PQQUCY1ZO7wIbAwULCQgHAwUVCgkICwUWAgMBAAIe 81 | AQIXgAAKCRBroPWiA39PQU8BAQDZOcoXzOZ8Mfr8B6/lE7D6f0TnqaDciX4k3GeP 82 | K3u9jwD6AlbgrA7qwghm4fN68IFR4+hiOqUndLd+adA4icgjewa4OARjVk7vEgor 83 | BgEEAZdVAQUBAQdAbog0UQCVqCgAWUfnuloWmVGxdzsSPtNigStOGkXdqR8DAQgH 84 | iHgEGBYKACAWIQRp5kceOuBlKXUpgy5roPWiA39PQQUCY1ZO7wIbDAAKCRBroPWi 85 | A39PQXDtAP9Gt1as8r9QDctUbzcGfOW0ZCtQrNnz3D5wX9eSALfykgD5AeZYzZ5C 86 | agLMQPij6Xr2Q708TMVle+0efR6aWboniAyZAg0EYr2NUAEQALQAOiMj8i/qrXHK 87 | BqThqTxLWRdIgloJn3hldtowfkpciv54alRctCiFYNlBUy2I6fvO/Mw4tc6R6fpR 88 | 24Q27L5HxHLAnnP+JI7Tw6caBO4apTbdx9SfvoP1zj416kYYNx9kmN9zyrvfzGtg 89 | Eo+Qz/VuPhBc+MH4XsSf77/w5vVNkIScJYR20W5B9lQRUpKs/CthYt44lTkixiM5 90 | tk7Om4NpJt6FzPJXxunVpjt7+B/fRValNRbD2V0sZM7ZfZPShVcmWsfOVpiifBvU 91 | FynqhFzx5+Q5QpERwT74RWNwdJ3mLwcVLkON3K8NU6AptVNf0M7raZDl9OYQS1Z5 92 | 6aWp7sGLq9JxnViELTNSSVDJWyTTyRZIw//ZUO0UIDMZrAh6wIdFe/B/wNgeUmTa 93 | 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 299 | ojxoVUI7jECl0Qzai6VbDuTBQsI= 300 | =MOll 301 | -----END PGP PUBLIC KEY BLOCK----- 302 | -------------------------------------------------------------------------------- /keys/qubes-repo-archlinux-key-4.1.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mQINBF+YUR4BEADHeJl8SfTMTqwendDgkVfD5r/YHEkRc40K7lR81cwY8f72ACvp 4 | zhKmGokSHf1QhL+TSdJVvB5Y3T3nfFLrc2Z9w9arK04SA53yXMKOIqdWygYHw0/c 5 | 1Ld6RswD/U2myZbFjSkfE8ud4JwYVNrZZL8ctO5Ozib8r/cGn/OGwI3mo5e+f35d 6 | d7v/GVfm7l6M5PaHI189VB7zBh4t/dkq79ujdIvR++hA6gWTBFr9u67c/8Hc8KN6 7 | pTq0Wd9Rg+VDKGCodiTuNFPnEeAMgvmYn18oDAfFsARIQPMpnejC4ONbpB7+yzts 8 | Z+W9Wni7/LoYlG0qjBa4koxRbhXfzCE/ebHkFt9myc4Aoh89ObqNzLeuAt8Xc3Uu 9 | 7U/6EU4SrQS0w8Ax9TqKEyzm2CsHF+koz5ElcYYNsarzloZzDqDY3arfyWJEbbEi 10 | wMY+nnzHXYudRSOlR6O7GPZDOvrqaZpyoZx58VIc//xci8cc+LNTRfqFZq15pB+z 11 | MMpzywriruLtyr9HRdSRkYd/kegDBt279ia11NfAHb6DymFno3BNHZ2zcb5njgLy 12 | fsl98F9aYbuQPJUZXSgr7u+bbqSNcEAzEb1j4y1LDQdounGT8yv+NoPoWug0R0MW 13 | VYe8Lae4W18QmUjFTRSpjqUXCg3wHO+ARrRuMe8XaOXyPnPFT50JrkCs4wARAQAB 14 | tClRdWJlcyBPUyA0IEFyY2hsaW51eCBQYWNrYWdlcyBTaWduaW5nIEtleYkCTgQT 15 | AQgAOBYhBM7fAD1UTM0dE4LpE4qHGhu9cJPqBQJfmFEeAhsDBQsJCAcCBhUKCQgL 16 | AgQWAgMBAh4BAheAAAoJEIqHGhu9cJPqXFAQAINy9aj9StfK9QhPZqUP6qk+sFFd 17 | /pKZ9z0mNgSALFSQP7K1K3EPCAcRvCPgHADgHBLBQrLRZASaocHXdB5F9nGHK5XG 18 | V4eB3jhJ96VovdWaq+d1ZPI0kOYD3VPyLErrGAk0BjaVXEIq7+8Y8cEldvEzLpQc 19 | tJr+issj/X0Cn2zN4WD8Uho1NQum59yOTvnviytmgi89EtRBKm7cLAyExx0+2dOR 20 | 0rleD6ONFLDMTcd8xykQUxFUrCD86g9yoQsoxVfNhOvwFnDjb7oFDhIkuiFKlQdc 21 | A1kQSHB/WaTFDaAsxHpe6IzHAzS5Z4dlXmdSu3JlJ5w5w61wa+8kd55P+1PuFxaz 22 | Fu6ZVpfehhhLsF7sqvxqEme2ugsy2eji3kIgU5PrVNzyiWxNehBDpPsbnMeDr1GE 23 | 5m6YY4Qw2PKvlOsnXbM1jIPpdZ20E9+L+2PePZc3QJKxJ60xOcuNMGCabq65v7/E 24 | 8zWn5DH99oyZan6SbhULzns4dlfYU1jRTIqKvoFXcWarEDa6OIHxn5Vixa5RMCAa 25 | 7qZbqc2MOI6SNxPtmpN1xaXzwqQIPpYDtXQ5M+Zr852zkk1glKjaysv6pRnKjh8p 26 | t7psLGVi++lZDwFSOcOo/zo+TvWXIf7m2GNTyIdPo9gnD8hhKqzy5jKK8QW08w2/ 27 | 8NQWJHD0YQS8dpId 28 | =xCJt 29 | -----END PGP PUBLIC KEY BLOCK----- 30 | -------------------------------------------------------------------------------- /keys/qubes-repo-archlinux-key-4.2.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mDMEZEfYRxYJKwYBBAHaRw8BAQdAFntzAP5EuGLtPQd9xc7CrEijCbCc+EBSXKy/ 4 | Mg9tnpe0K1F1YmVzIE9TIDQuMiBBcmNobGludXggUGFja2FnZXMgU2lnbmluZyBL 5 | ZXmIkwQTFgoAOxYhBOUAHB1JvpEp3uwGKExicBRsRj2QBQJkR9hHAhsDBQsJCAcC 6 | AiICBhUKCQgLAgQWAgMBAh4HAheAAAoJEExicBRsRj2QGWYBAL8w9P1l2KJ2Ez4h 7 | KKXOEtXREVzcTZrFjJLLTt8fmt8jAQC6OP5BXJmFSHsURZdlH1URyoEPHOs0hRgm 8 | FDxJL2CVDQ== 9 | =O71O 10 | -----END PGP PUBLIC KEY BLOCK----- 11 | -------------------------------------------------------------------------------- /keys/qubes-repo-archlinux-key-4.3.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mDMEZh8haxYJKwYBBAHaRw8BAQdAzDlTNsneY90VJcYqvYykwsfB48JJZ3PmnX1H 4 | 68Wy0YW0K1F1YmVzIE9TIDQuMyBBcmNobGludXggUGFja2FnZXMgU2lnbmluZyBL 5 | ZXmIkwQTFgoAOxYhBPPfvXBVij9F8Bp7o6sYfJ+FvfzABQJmHyFrAhsDBQsJCAcC 6 | AiICBhUKCQgLAgQWAgMBAh4HAheAAAoJEKsYfJ+FvfzAChUA/05VXoSsF8IQRQ8l 7 | 1ADHykR38V5/FhGOxunzkYEscAeeAP9+Gw45/epHfg4+chVv1byfFsqqxUGuakZP 8 | JuS0tIKmDg== 9 | =MQM8 10 | -----END PGP PUBLIC KEY BLOCK----- 11 | -------------------------------------------------------------------------------- /keys/qubes-repo-archlinux-key.asc: -------------------------------------------------------------------------------- 1 | qubes-repo-archlinux-key-4.2.asc -------------------------------------------------------------------------------- /prepare-chroot-base: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # vim: set ts=4 sw=4 sts=4 et : 3 | ### prepare-chroot-base : Create a (any) chroot instance of Archlinux 4 | ### May be called from ./template_archlinux/01_install_core.sh or ./prepare-chroot-archlinux 5 | echo "--> Archlinux prepare-chroot-base" 6 | 7 | set -e 8 | if [ "$VERBOSE" -ge 2 ] || [ "$DEBUG" -gt 0 ]; then 9 | set -x 10 | fi 11 | 12 | INSTALL_DIR="$1" 13 | 14 | BOOTSTRAP_DIR="${CACHE_DIR}/bootstrap" 15 | DEFAULT_ARCHLINUX_MIRROR="\ 16 | https://mirror.rackspace.com/archlinux\ 17 | ,https://arch.mirror.constant.com\ 18 | ,https://mirror.f4st.host/archlinux\ 19 | ,https://mirrors.edge.kernel.org/archlinux\ 20 | " 21 | ARCHLINUX_MIRROR="${ARCHLINUX_MIRROR:-$DEFAULT_ARCHLINUX_MIRROR}" 22 | IFS="," read -r -a ARCHLINUX_MIRROR <<< "$ARCHLINUX_MIRROR" 23 | 24 | PACMAN_CACHE_DIR="${CACHE_DIR}/pacman_cache" 25 | export PACMAN_CACHE_DIR 26 | 27 | exit_prepare() { 28 | local exit_code=$? 29 | echo " --> Unbinding INSTALL_DIR..." 30 | umount "${BOOTSTRAP_DIR}/mnt" || true 31 | exit $exit_code 32 | } 33 | 34 | trap 'exit_prepare' 0 1 2 3 6 15 35 | 36 | if ! { [ -f "${BOOTSTRAP_DIR}/.extracted" ] && [ -d "${CACHE_DIR}/pacman_cache" ] ;}; then 37 | # XXX: Potential infinite loop in certain error conditions? 38 | echo " --> Bootstrap chroot environment may not exist, calling 00_prepare.sh..." 39 | "${TEMPLATE_CONTENT_DIR}/00_prepare.sh" 40 | fi 41 | 42 | # XXX: Also run if .extracted is newer than .prepared_base ?? 43 | if [ -f "${INSTALL_DIR}/.prepared_base" ]; then 44 | echo " --> NB: INSTALL_DIR '${INSTALL_DIR}' already appears to have an environment; will leave as-is!" 45 | exit 0 46 | fi 47 | 48 | echo " --> Binding INSTALL_DIR '${INSTALL_DIR}' to bootstrap environment..." 49 | mount --bind "$INSTALL_DIR" "${BOOTSTRAP_DIR}/mnt" 50 | 51 | echo -e " --> Setting pacman mirrorlist as:\n$(echo "${ARCHLINUX_MIRROR[@]}" | tr ' ' '\n')\n" 52 | for MIRROR_ENTRY in "${ARCHLINUX_MIRROR[@]}"; do 53 | echo "Server = $MIRROR_ENTRY/\$repo/os/\$arch" 54 | done > "${BOOTSTRAP_DIR}/etc/pacman.d/mirrorlist" 55 | 56 | cp /etc/resolv.conf "${BOOTSTRAP_DIR}/etc/" 57 | 58 | echo " --> Initializing pacman keychain..." 59 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$BOOTSTRAP_DIR" /bin/sh -c \ 60 | "pacman-key --init && pacman-key --populate" 61 | 62 | echo " --> Installing core pacman packages..." 63 | export PACMAN_CACHE_MOUNT_DIR="${BOOTSTRAP_DIR}/mnt/var/cache/pacman" 64 | # shellcheck disable=SC2016 65 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$BOOTSTRAP_DIR" /bin/sh -c \ 66 | 'trap break SIGINT SIGTERM; for i in 1 2 3 4 5; do ALL_PROXY=$1 http_proxy=$1 https_proxy=$1 NO_PROXY=127.0.0.1 pacstrap /mnt base && exit 0; done' sh "$REPO_PROXY" 67 | unset PACMAN_CACHE_MOUNT_DIR 68 | 69 | touch "${INSTALL_DIR}/.prepared_base" 70 | -------------------------------------------------------------------------------- /prepare-chroot-builder: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim: set ts=4 sw=4 sts=4 et : 3 | 4 | ### prepare-chroot-builder : Create the build chroot instance of Archlinux 5 | ### (in which to build Qubes packages) 6 | echo "--> Archlinux prepare-chroot-builder" 7 | 8 | set -eu 9 | if [ "${VERBOSE:-0}" -ge 2 ] || [ "${DEBUG:-0}" -eq 1 ]; then 10 | set -x 11 | fi 12 | 13 | INSTALL_DIR="$1" 14 | CACHE_DIR="$2" 15 | 16 | PACMAN_CACHE_DIR="${CACHE_DIR}/pacman_cache" 17 | export CACHE_DIR PACMAN_CACHE_DIR 18 | 19 | # do not make volatile private key dir for the package builds themselves 20 | # this is interpreted by template_archlinux/arch-chroot-lite 21 | SKIP_VOLATILE_SECRET_KEY_DIR=true 22 | export SKIP_VOLATILE_SECRET_KEY_DIR 23 | 24 | # Support legacy builder 25 | if [ -n "${TEMPLATE_SCRIPTS:-}" ]; then 26 | TEMPLATE_CONTENT_DIR="${TEMPLATE_SCRIPTS}" 27 | export TEMPLATE_CONTENT_DIR 28 | fi 29 | if [ -z "${KEYS_DIR:-}" ]; then 30 | KEYS_DIR="${TEMPLATE_CONTENT_DIR}/../keys" 31 | export KEYS_DIR 32 | fi 33 | 34 | # /home/user will exist if we've completed the build previously 35 | if ! [ -d "${INSTALL_DIR}/home/user" ]; then 36 | # It's non-existence means this is likely the initial run, so build it 37 | 38 | mkdir -p "$INSTALL_DIR" 39 | 40 | echo " --> Installing archlinux build root:" 41 | "${TEMPLATE_CONTENT_DIR}/../prepare-chroot-base" "${INSTALL_DIR}" 42 | 43 | echo " --> Configure system accounts..." 44 | [ -n "${SUDO_UID:-}" ] && USER_OPTS="-u ${SUDO_UID}" 45 | [ -n "${USER_UID:-}" ] && USER_OPTS="-u ${USER_UID}" 46 | if [ -n "${USER_GID:-}" ]; then 47 | chroot "$INSTALL_DIR" /bin/groupadd -g "$USER_GID" user 48 | elif [ -n "${SUDO_GID:-}" ]; then 49 | chroot "$INSTALL_DIR" /bin/groupadd -g "$SUDO_GID" user 50 | else 51 | chroot "$INSTALL_DIR" /bin/groupadd user 52 | fi 53 | chroot "$INSTALL_DIR" /bin/sh -c \ 54 | "useradd -g user -G wheel $USER_OPTS -m user; su -c 'mkdir qubes-src' - user" 55 | 56 | echo " --> Synchronize resolv.conf..." 57 | cp /etc/resolv.conf "${INSTALL_DIR}/etc/resolv.conf" 58 | 59 | # Checking for free disk free space doesn't work in chroots 60 | echo " --> Comment out CheckSpace in pacman.conf..." 61 | sed 's/^ *CheckSpace/#CheckSpace/g' -i "${INSTALL_DIR}/etc/pacman.conf" 62 | 63 | echo " --> Installing required makepkg dependencies..." 64 | pkgs="base-devel binutils fakeroot sudo" 65 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 66 | "http_proxy='${REPO_PROXY:-}' pacman -Sy --needed --noconfirm --noprogressbar --asdeps $pkgs" 67 | 68 | # makepkg internally calls sudo without '-E', so we need to add an 69 | # env_keep to honor proxy settings 70 | echo " --> Configure sudo..." 71 | cat > "${INSTALL_DIR}/etc/sudoers.d/qubes-build-user" <> "${INSTALL_DIR}/etc/pacman.conf" 94 | fi 95 | cat "${TEMPLATE_CONTENT_DIR}/../repos/archlinux-qubes-repo-${USE_QUBES_REPO_VERSION}-current.conf" >> "${INSTALL_DIR}/etc/pacman.conf" 96 | key_fpr=$(gpg --with-colons --show-key "${KEYS_DIR}/qubes-repo-archlinux-key-${USE_QUBES_REPO_VERSION}.asc" | grep ^fpr: | cut -d : -f 10) 97 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" pacman-key --add - < "${KEYS_DIR}/qubes-repo-archlinux-key-${USE_QUBES_REPO_VERSION}.asc" 98 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" pacman-key --lsign "$key_fpr" 99 | fi 100 | fi 101 | -------------------------------------------------------------------------------- /repos/archlinux-qubes-repo-4.1-current-testing.conf: -------------------------------------------------------------------------------- 1 | [qubes-r4.1-current-testing] 2 | Server = https://archlinux.qubes-os.org/r4.1/current-testing/vm/archlinux/pkgs 3 | -------------------------------------------------------------------------------- /repos/archlinux-qubes-repo-4.1-current.conf: -------------------------------------------------------------------------------- 1 | [qubes-r4.1-current] 2 | Server = https://archlinux.qubes-os.org/r4.1/current/vm/archlinux/pkgs 3 | -------------------------------------------------------------------------------- /repos/archlinux-qubes-repo-4.2-current-testing.conf: -------------------------------------------------------------------------------- 1 | [qubes-r4.2-current-testing] 2 | Server = https://archlinux.qubes-os.org/r4.2/current-testing/vm/archlinux/pkgs 3 | -------------------------------------------------------------------------------- /repos/archlinux-qubes-repo-4.2-current.conf: -------------------------------------------------------------------------------- 1 | [qubes-r4.2-current] 2 | Server = https://archlinux.qubes-os.org/r4.2/current/vm/archlinux/pkgs 3 | -------------------------------------------------------------------------------- /repos/archlinux-qubes-repo-4.3-current-testing.conf: -------------------------------------------------------------------------------- 1 | [qubes-r4.3-current-testing] 2 | Server = https://archlinux.qubes-os.org/r4.3/current-testing/vm/archlinux/pkgs 3 | -------------------------------------------------------------------------------- /repos/archlinux-qubes-repo-4.3-current.conf: -------------------------------------------------------------------------------- 1 | [qubes-r4.3-current] 2 | Server = https://archlinux.qubes-os.org/r4.3/current/vm/archlinux/pkgs 3 | -------------------------------------------------------------------------------- /template_archlinux/00_prepare.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -- 2 | 3 | set -euo pipefail 4 | if [ "${VERBOSE:-0}" -ge 2 ] || [ "${DEBUG:-0}" -eq 1 ]; then 5 | set -x 6 | fi 7 | 8 | # Support for legacy builder 9 | # shellcheck disable=SC2153 10 | if [ "0${IS_LEGACY_BUILDER:-0}" -eq 1 ]; then 11 | KEYS_DIR="${TEMPLATE_CONTENT_DIR}/../keys" 12 | export KEYS_DIR 13 | fi 14 | 15 | echo "--> Archlinux 00_prepare.sh" 16 | 17 | if [[ -n "${REPO_PROXY+x}" ]]; then 18 | export "https_proxy=$REPO_PROXY" "http_proxy=$REPO_PROXY" 19 | fi 20 | ARCHLINUX_SRC_PREFIX="${ARCHLINUX_SRC_PREFIX:-https://mirrors.edge.kernel.org/archlinux}" 21 | BOOTSTRAP_TARBALL=$(wget -O- "$ARCHLINUX_SRC_PREFIX"/iso/latest/sha256sums.txt | grep -o "archlinux-bootstrap-[0-9.]*-x86_64\.tar\.[a-z]*" | head -1) 22 | BOOTSTRAP_URL="${ARCHLINUX_SRC_PREFIX}/iso/latest/${BOOTSTRAP_TARBALL}" 23 | 24 | mkdir -p "${CACHE_DIR}/pacman_cache" 25 | 26 | echo " --> Downloading Archlinux bootstrap tarball (v${ARCHLINUX_REL_VERSION-})..." 27 | 28 | wget -N -P "$CACHE_DIR" "$BOOTSTRAP_URL" 29 | wget -N -P "$CACHE_DIR" "${BOOTSTRAP_URL}.sig" 30 | 31 | echo " --> Preparing GnuPG to verify tarball..." 32 | mkdir -p "${CACHE_DIR}/gpghome" 33 | touch "${CACHE_DIR}/gpghome/pubring.gpg" 34 | chmod -R go-rwx "${CACHE_DIR}/gpghome" 35 | gpg --keyring "${CACHE_DIR}/gpghome/pubring.gpg" --import "${KEYS_DIR}/archlinux-master-keys.asc" || exit 36 | 37 | echo " --> Verifying tarball..." 38 | gpg --keyring "${CACHE_DIR}/gpghome/pubring.gpg" --verify "${CACHE_DIR}/${BOOTSTRAP_TARBALL}.sig" "${CACHE_DIR}/${BOOTSTRAP_TARBALL}" || exit 39 | 40 | if [ "${CACHE_DIR}/${BOOTSTRAP_TARBALL}" -nt "${CACHE_DIR}/bootstrap/.extracted" ]; then 41 | echo " --> Extracting bootstrap tarball (nuking previous directory)..." 42 | rm -rf "${CACHE_DIR}/bootstrap/" 43 | mkdir -p "${CACHE_DIR}/bootstrap" 44 | # By default will extract to a "root.x86_64" directory; strip that off 45 | tar -xC "${CACHE_DIR}/bootstrap" --strip-components=1 -f "${CACHE_DIR}/${BOOTSTRAP_TARBALL}" 46 | # Copy the distribution-provided version to be rewritten based on the 47 | # value of $ARCHLINUX_MIRROR each run (by the Makefile) 48 | cp -a "${CACHE_DIR}/bootstrap/etc/pacman.d/mirrorlist" "${CACHE_DIR}/bootstrap/etc/pacman.d/mirrorlist.dist" 49 | touch "${CACHE_DIR}/bootstrap/.extracted" 50 | else 51 | echo " --> NB: Bootstrap tarball not newer than bootstrap directory, will use existing!" 52 | fi 53 | -------------------------------------------------------------------------------- /template_archlinux/01_install_core.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # vim: set ts=4 sw=4 sts=4 et : 3 | ### 01_install_core.sh : Create build chroot install of Archlinux using pacstrap 4 | echo "--> Archlinux 01_install_core.sh" 5 | 6 | set -e 7 | if [ "${VERBOSE:-0}" -ge 2 ] || [ "${DEBUG:-0}" -eq 1 ]; then 8 | set -x 9 | fi 10 | 11 | # make sure pacman master private key is _not_ stored in the TemplateVM - see 12 | # template_archlinux/arch-chroot-lite for details 13 | unset SKIP_VOLATILE_SECRET_KEY_DIR 14 | 15 | "${TEMPLATE_CONTENT_DIR}/../prepare-chroot-base" "$INSTALL_DIR" "$DIST" 16 | -------------------------------------------------------------------------------- /template_archlinux/02_install_groups.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # vim: set ts=4 sw=4 sts=4 et : 3 | ### 02_install_groups.sh : Install specified additional packages into chroot 4 | echo "--> Archlinux 02_install_groups.sh" 5 | 6 | set -e 7 | if [ "${VERBOSE:-0}" -ge 2 ] || [ "${DEBUG:-0}" -eq 1 ]; then 8 | set -x 9 | fi 10 | 11 | if [ -n "$TEMPLATE_FLAVOR" ]; then 12 | PKGLISTFILE="${TEMPLATE_CONTENT_DIR}/packages_${TEMPLATE_FLAVOR}.list" 13 | if ! [ -r "$PKGLISTFILE" ]; then 14 | echo "ERROR: PKGLISTFILE '${PKGLISTFILE}' does not exist!" 15 | exit 1 16 | fi 17 | else 18 | PKGLISTFILE="${TEMPLATE_CONTENT_DIR}/packages.list" 19 | fi 20 | 21 | # Strip comments, then convert newlines to single spaces 22 | PKGGROUPS="$(sed '/^ *#/d; s/ *#.*//' "${PKGLISTFILE}" | sed ':a;N;$!ba; s/\n/ /g; s/ */ /g')" 23 | 24 | if [ "$RELEASE" == "4.2" ]; then 25 | # Force pulseaudio over pipewire on 4.2 - otherwise pipewire-pulse gets 26 | # installed that later conflicts with pulseaudio 27 | PKGGROUPS+=" pulseaudio" 28 | fi 29 | 30 | PACMAN_CACHE_DIR="${CACHE_DIR}/pacman_cache" 31 | export PACMAN_CACHE_DIR 32 | 33 | echo " --> Synchronize resolv.conf..." 34 | cp /etc/resolv.conf "${INSTALL_DIR}/etc/resolv.conf" 35 | 36 | echo " --> Updating installed packages..." 37 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 38 | "http_proxy='${REPO_PROXY}' pacman -Syu --noconfirm --noprogressbar" 39 | 40 | echo " --> Installing archlinux package groups..." 41 | echo " --> Selected packages: ${PKGGROUPS}" 42 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 43 | "http_proxy='${REPO_PROXY}' pacman -S --needed --noconfirm --noprogressbar ${PKGGROUPS}" 44 | -------------------------------------------------------------------------------- /template_archlinux/04_install_qubes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # vim: set ts=4 sw=4 sts=4 et : 3 | ### 04_install_qubes.sh : Prepare chroot instance as a Qubes template 4 | echo "--> Archlinux 04_install_qubes.sh" 5 | 6 | set -e 7 | if [ "$VERBOSE" -ge 2 ] || [ "$DEBUG" -gt 0 ]; then 8 | set -x 9 | fi 10 | 11 | # Support for legacy builder 12 | if [ -n "$CACHEDIR" ]; then 13 | CACHE_DIR="$CACHEDIR" 14 | fi 15 | 16 | PACMAN_CACHE_DIR="${CACHE_DIR}/pacman_cache" 17 | 18 | if [ "0${IS_LEGACY_BUILDER}" -eq 1 ]; then 19 | PACMAN_CUSTOM_REPO_DIR="${PWD}/pkgs-for-template/${DIST}" 20 | else 21 | PACMAN_CUSTOM_REPO_DIR="${PACKAGES_DIR}" 22 | fi 23 | 24 | export PACMAN_CACHE_DIR PACMAN_CUSTOM_REPO_DIR "ALL_PROXY=$REPO_PROXY" NO_PROXY=127.0.0.1 25 | 26 | echo " --> Enabling x86 repos..." 27 | su -c "echo '[multilib]' >> $INSTALL_DIR/etc/pacman.conf" 28 | su -c "echo 'SigLevel = PackageRequired' >> $INSTALL_DIR/etc/pacman.conf" 29 | su -c "echo 'Include = /etc/pacman.d/mirrorlist' >> $INSTALL_DIR/etc/pacman.conf" 30 | sudo sed -Ei 's,^#(Server *= *https://mirrors\.kernel\.org/),\1,' "$INSTALL_DIR/etc/pacman.d/mirrorlist" 31 | 32 | echo " --> Updating Qubes custom repository..." 33 | # Repo Add need packages to be added in the right version number order as it only keeps the last entered package version 34 | # shellcheck disable=SC2016 35 | 36 | 37 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 38 | 'mkdir -p /tmp/qubes-packages-mirror-repo/pkgs' 39 | 40 | PKGS_DIR="$PACMAN_CUSTOM_REPO_DIR/pkgs" 41 | # repo-add cannot create empty db anymore, do it manually 42 | bsdtar -cf - -T /dev/null | gzip > "${PKGS_DIR}/qubes.db.tar.gz" 43 | ln -s qubes.db.tar.gz "${PKGS_DIR}/qubes.db" 44 | bsdtar -cf - -T /dev/null | gzip > "${PKGS_DIR}/qubes.files.tar.gz" 45 | ln -s qubes.files.tar.gz "${PKGS_DIR}/qubes.files" 46 | 47 | if [ "0${IS_LEGACY_BUILDER}" -eq 0 ]; then 48 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 49 | "cd /tmp/qubes-packages-mirror-repo && find . -name '*.pkg.tar.*' -print0 | xargs -0 -I {} mv {} pkgs/" 50 | fi 51 | 52 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 53 | 'cd /tmp/qubes-packages-mirror-repo && for pkg in `ls -v pkgs/*.pkg.tar.zst`; do [ -f "$pkg" ] && repo-add pkgs/qubes.db.tar.gz "$pkg"; done;' 54 | 55 | chown -R --reference="$PACMAN_CUSTOM_REPO_DIR" "$PACMAN_CUSTOM_REPO_DIR" 56 | 57 | echo " --> Registering Qubes custom repository..." 58 | echo "### qubes-builder-begin" >> "$INSTALL_DIR/etc/pacman.conf" 59 | echo "[qubes] " | sudo tee -a "$INSTALL_DIR/etc/pacman.conf" 60 | echo "SigLevel = Never " | sudo tee -a "$INSTALL_DIR/etc/pacman.conf" 61 | echo "Server = file:///tmp/qubes-packages-mirror-repo/pkgs " | sudo tee -a "$INSTALL_DIR/etc/pacman.conf" 62 | 63 | run_pacman () { 64 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 65 | 'proxy=$1; shift; trap break SIGINT SIGTERM; for i in 1 2 3 4 5; do ALL_PROXY=$proxy http_proxy=$proxy https_proxy=$proxy NO_PROXY=127.0.0.1 "$@" && exit; done; exit 1' sh "$REPO_PROXY" pacman "$@" 66 | } 67 | 68 | run_pacman_single () { 69 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 70 | 'proxy=$1; shift; trap break SIGINT SIGTERM; ALL_PROXY=$proxy http_proxy=$proxy https_proxy=$proxy NO_PROXY=127.0.0.1 "$@"' sh "$REPO_PROXY" pacman "$@" 71 | } 72 | 73 | echo " --> Synchronize resolv.conf..." 74 | cp -- /etc/resolv.conf "${INSTALL_DIR}/etc/resolv.conf" 75 | 76 | echo " --> Updating pacman sources..." 77 | run_pacman -Syu --noconfirm --noprogressbar 78 | 79 | echo " --> Checking available qubes packages (for debugging only)..." 80 | run_pacman_single -Ss qubes || : 81 | 82 | if [ -n "$USE_QUBES_REPO_VERSION" ]; then 83 | # we don't check specific value here, assume correct branch of 84 | # meta-packages component 85 | echo " --> Installing repository qubes package..." 86 | repos_basename="${TEMPLATE_CONTENT_DIR}/../repos/archlinux-qubes-repo-${USE_QUBES_REPO_VERSION}" 87 | key_path="${TEMPLATE_CONTENT_DIR}/../keys/qubes-repo-archlinux-key-${USE_QUBES_REPO_VERSION}.asc" 88 | if [ "0$USE_QUBES_REPO_TESTING" -gt 0 ]; then 89 | echo " --> Enabling current-testing repository..." 90 | cat "${repos_basename}-current-testing.conf" \ 91 | >> "$INSTALL_DIR/etc/pacman.conf" 92 | fi 93 | cat "${repos_basename}-current.conf" \ 94 | >> "$INSTALL_DIR/etc/pacman.conf" 95 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" pacman-key --add /proc/self/fd/0 < "${key_path}" 96 | key_fpr=$(gpg --with-colons --show-key "${key_path}"| grep ^fpr: | cut -d : -f 10) 97 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" pacman-key --lsign "$key_fpr" 98 | echo " --> Updating pacman sources..." 99 | run_pacman -Syu --noconfirm --noprogressbar 100 | fi 101 | echo "### qubes-builder-end" >> "$INSTALL_DIR/etc/pacman.conf" 102 | 103 | echo " --> Installing mandatory qubes packages..." 104 | run_pacman -S --noconfirm --noprogressbar qubes-vm-dependencies 105 | 106 | echo " --> Installing recommended qubes apps" 107 | run_pacman -S --noconfirm --noprogressbar qubes-vm-recommended 108 | 109 | echo " --> Installing repository qubes package..." 110 | run_pacman -S --noconfirm --noprogressbar qubes-vm-repo 111 | 112 | if ! grep -q /dmroot "${INSTALL_DIR}/etc/fstab"; then 113 | echo " --> Updating template fstab file..." 114 | cat >> "${INSTALL_DIR}/etc/fstab" < Configuring system to our preferences..." 138 | # Name network devices using simple names (ethX) 139 | ln -s /dev/null "${INSTALL_DIR}/etc/udev/rules.d/80-net-name-slot.rules" 140 | # Enable some locales (incl. UTF-8) 141 | sed 's/#en_US/en_US/g' -i "${INSTALL_DIR}/etc/locale.gen" 142 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" locale-gen 143 | echo 'LANG=en_US.UTF-8' > "${INSTALL_DIR}/etc/locale.conf" 144 | 145 | # Creating a random file in /lib/modules to ensure that the directory in never deleted when packages are removed 146 | mkdir -p "${INSTALL_DIR}/lib/modules" 147 | touch "${INSTALL_DIR}/lib/modules/QUBES_NODELETE" 148 | 149 | # Remove qubes local repository definition 150 | sed '/### qubes-builder-begin/,/### qubes-builder-end/d' -i "${INSTALL_DIR}/etc/pacman.conf" 151 | -------------------------------------------------------------------------------- /template_archlinux/09_cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # vim: set ts=4 sw=4 sts=4 et : 3 | ### 09_cleanup.sh : Clean up the new chroot prior to image finalisation 4 | echo "--> Archlinux 09_cleanup.sh" 5 | 6 | set -e 7 | if [ "${VERBOSE:-0}" -ge 2 ] || [ "${DEBUG:-0}" -eq 1 ]; then 8 | set -x 9 | fi 10 | 11 | # Remove unused packages and their dependencies (make dependencies) 12 | cleanuppkgs="$("${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c 'pacman -Qdt | grep -v kernel | cut -d " " -f 1')" 13 | if [ -n "$cleanuppkgs" ] ; then 14 | echo " --> Packages that will be cleaned up: $cleanuppkgs" 15 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c "pacman --noconfirm -Rsc $cleanuppkgs" 16 | else 17 | echo " --> NB: No packages to clean up" 18 | fi 19 | 20 | # TODO: Be more deliberate here; is the umount necessary? 21 | # Moreover, given where this script is called, should we be bothering 22 | # arch-chroot-lite? 23 | echo " --> Cleaning up pacman state..." 24 | umount "${INSTALL_DIR}/var/cache/pacman" || true 25 | unset PACMAN_CACHE_DIR 26 | "${TEMPLATE_CONTENT_DIR}/arch-chroot-lite" "$INSTALL_DIR" /bin/sh -c \ 27 | "pacman --noconfirm -Scc" 28 | 29 | echo " --> Cleaning /etc/resolv.conf" 30 | rm -f "${INSTALL_DIR}/etc/resolv.conf" 31 | cat > "${INSTALL_DIR}/etc/resolv.conf" << EOF 32 | # This file intentionally left blank 33 | 34 | EOF 35 | -------------------------------------------------------------------------------- /template_archlinux/appmenus_archlinux/netvm-whitelisted-appmenus.list: -------------------------------------------------------------------------------- 1 | xfce4-terminal.desktop 2 | -------------------------------------------------------------------------------- /template_archlinux/appmenus_archlinux/vm-whitelisted-appmenus.list: -------------------------------------------------------------------------------- 1 | xfce4-terminal.desktop 2 | thunar.desktop 3 | firefox.desktop 4 | -------------------------------------------------------------------------------- /template_archlinux/appmenus_archlinux/whitelisted-appmenus.list: -------------------------------------------------------------------------------- 1 | xfce4-terminal.desktop -------------------------------------------------------------------------------- /template_archlinux/appmenus_archlinux_minimal/netvm-whitelisted-appmenus.list: -------------------------------------------------------------------------------- 1 | xterm.desktop 2 | -------------------------------------------------------------------------------- /template_archlinux/appmenus_archlinux_minimal/vm-whitelisted-appmenus.list: -------------------------------------------------------------------------------- 1 | xterm.desktop 2 | -------------------------------------------------------------------------------- /template_archlinux/appmenus_archlinux_minimal/whitelisted-appmenus.list: -------------------------------------------------------------------------------- 1 | xterm.desktop 2 | -------------------------------------------------------------------------------- /template_archlinux/arch-chroot-lite: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### 3 | ### A stripped-down version of the 'arch-chroot' script bundled with Archlinux 4 | ### 5 | ### This version drops unused code and makes a fey key modifications, 6 | ### annotated where they occur below. 7 | ### 8 | 9 | shopt -s extglob 10 | 11 | die() { error "$@"; exit 1; } 12 | 13 | chroot_add_mount() { 14 | mount "$@" && CHROOT_ACTIVE_MOUNTS=("$2" "${CHROOT_ACTIVE_MOUNTS[@]}") 15 | } 16 | 17 | setup_volatile_secret_key_dir() { 18 | if [ "$SKIP_VOLATILE_SECRET_KEY_DIR" = "true" ]; then 19 | return 20 | fi 21 | 22 | # This directory stores secret GPG keys, so its contents must be kept secret 23 | # at all costs. Anyone with access to the files in it can compromise the 24 | # built TemplateVM and all VMs based on it. 25 | secret_key_dir="$1/etc/pacman.d/gnupg/private-keys-v1.d" && 26 | 27 | # private-keys-v1.d does not exist before we create the tmpfs 28 | mkdir -p -m 0755 -- "${secret_key_dir%/*}" && 29 | mkdir -p -m 0000 -- "$secret_key_dir" && 30 | 31 | # Create README 32 | [[ -f "$secret_key_dir/README" ]] || cat > "$secret_key_dir/README" <<'EOF' && 33 | # Why is this directory immutable? 34 | 35 | In QubesOS, a TemplateVM’s root volume is readable by all AppVMs based on it. 36 | Therefore, it cannot be used to store secret data. 37 | 38 | Pacman relies on the secrecy of its master key, which is normally stored in 39 | `/etc/pacman.d/gnupg/private-keys-v1.d`. Anyone who has this key can sign 40 | packages that Pacman will accept. Therefore, this key must not be stored on the 41 | root volume. Furthermore, a user might (quite reasonably) assume that there is 42 | no sensitive information on a TemplateVM’s private volume unless they have added 43 | it explicitly. So the master key cannot be stored there either. 44 | 45 | The only remaining option is to use an ephemeral key that is only kept in 46 | memory. That is what QubesOS does: during the build process, a ramfs is mounted 47 | over /etc/pacman.d/gnupg/private-keys-v1.d, so that the secret key is kept in 48 | memory. When the ramfs is unmounted, the key is destroyed along with it. 49 | 50 | There is one remaining problem: relying on a mount point is not fail-safe. If 51 | the ramfs fails to mount, or if the user later runs operations like 52 | `pacman-key --init`, a new master key will be generated. It will later be 53 | leaked to AppVMs based on this template. 54 | 55 | To prevent this potentially disasterous failure, QubesOS marks the directory as 56 | immutable. This ensures that nobody (not even root) can create any files in it. 57 | When GPG tries to write its secret key to disk, it will fail, preventing any 58 | leakage. 59 | 60 | P.S.: Why a ramfs and not a tmpfs? Data on a ramfs can never be paged out to 61 | disk, which ensures that this key is never leaked to swap partitions. GPG 62 | internally locks its memory into RAM to prevent similar problems. 63 | EOF 64 | # Mark private-keys-v1.d immutable, so that files (such as secret keys) 65 | # cannot accidentally be created in it. 66 | chattr -R +i -- "$secret_key_dir" && 67 | 68 | # See the README above for why this is a ramfs 69 | chroot_add_mount pacman-privkeys "$secret_key_dir" -t ramfs -o mode=000,nosuid,noexec,nodev || exit 70 | } 71 | 72 | chroot_setup() { 73 | CHROOT_ACTIVE_MOUNTS=() 74 | [[ $(trap -p EXIT) ]] && die '(BUG): attempting to overwrite existing EXIT trap' 75 | trap 'chroot_teardown' EXIT 76 | 77 | # arch-chroot-lite drops the conditional bind mount on the chroot path, as 78 | # it seemed to shadow mounts set up before arch-chroot was invoked 79 | 80 | # Set the correct permissions for mount points 81 | chmod -- 0755 "$1/dev" "$1/run" && 82 | chmod -- 0555 "$1/proc" "$1/sys" && 83 | chmod -- 1777 "$1/tmp" && 84 | 85 | mkdir -p "$1/dev/shm" && 86 | mkdir -p "$1/dev/pts" && 87 | for dev in null zero random urandom; do 88 | [ -c "$1/dev/$dev" ] || cp -a "/dev/$dev" "$1/dev/" 89 | done && 90 | 91 | setup_volatile_secret_key_dir && 92 | 93 | chroot_add_mount proc "$1/proc" -t proc -o nosuid,noexec,nodev && 94 | chroot_add_mount sys "$1/sys" -t sysfs -o nosuid,noexec,nodev,ro && 95 | # arch-chroot-lite will never have occasion to use efivars, so don't bother 96 | # mounting efivarfs here 97 | chroot_add_mount devpts "$1/dev/pts" -t devpts -o mode=0620,gid=5,nosuid,noexec && 98 | chroot_add_mount shm "$1/dev/shm" -t tmpfs -o mode=1777,nosuid,nodev && 99 | chroot_add_mount run "$1/run" -t tmpfs -o nosuid,nodev,mode=0755 && 100 | chroot_add_mount tmp "$1/tmp" -t tmpfs -o mode=1777,strictatime,nodev,nosuid && 101 | ln -nsf ../proc/self/fd "$1/dev/" || 102 | exit 103 | 104 | if [[ -d "$PACMAN_CACHE_DIR" ]]; then 105 | PACMAN_CACHE_MOUNT_DIR="${PACMAN_CACHE_MOUNT_DIR:-$1/var/cache/pacman}" 106 | mkdir -p "$PACMAN_CACHE_MOUNT_DIR" 107 | # Cached qubes packages may be from old runs and throw checksum errors 108 | rm "$PACMAN_CACHE_DIR/pkg"/qubes-*.pkg.tar.* 2>/dev/null || true 109 | chroot_add_mount "$PACMAN_CACHE_DIR" "$PACMAN_CACHE_MOUNT_DIR" --bind 110 | fi 111 | if [[ -d "$PACMAN_CUSTOM_REPO_DIR" ]]; then 112 | mkdir -p "$1/tmp/qubes-packages-mirror-repo" 113 | chroot_add_mount "$PACMAN_CUSTOM_REPO_DIR" "$1/tmp/qubes-packages-mirror-repo" --bind 114 | fi 115 | } 116 | 117 | chroot_teardown() { 118 | # arch-chroot-lite kills gpg-agent, started by pacman-key, which otherwise 119 | # keeps the mounts busy and prevents unmounting 120 | pkill gpg-agent 121 | umount "${CHROOT_ACTIVE_MOUNTS[@]}" 122 | unset CHROOT_ACTIVE_MOUNTS 123 | } 124 | 125 | usage() { 126 | cat < Archlinux update-local-repo.sh" 6 | 7 | PKGS_DIR="${BUILDER_REPO_DIR}/pkgs" 8 | 9 | [ "$VERBOSE" -ge 2 -o "$DEBUG" -gt 0 ] && set -x 10 | 11 | chroot_cmd() { 12 | systemd-nspawn --directory="$CHROOT_DIR" \ 13 | --keep-unit \ 14 | --register=no \ 15 | --bind="${BUILDER_REPO_DIR}":"/tmp/qubes-packages-mirror-repo" \ 16 | --chdir=/tmp/qubes-packages-mirror-repo \ 17 | "$@" 18 | } 19 | 20 | mkdir -p "$PKGS_DIR" 21 | if [ ! -f "${PKGS_DIR}/qubes.db" ]; then 22 | echo " -> Repo '${PKGS_DIR}' appears empty; initialising..." 23 | # repo-add cannot create empty db anymore, do it manually 24 | bsdtar -cf - -T /dev/null | gzip > "${PKGS_DIR}/qubes.db.tar.gz" 25 | ln -s qubes.db.tar.gz "${PKGS_DIR}/qubes.db" 26 | bsdtar -cf - -T /dev/null | gzip > "${PKGS_DIR}/qubes.files.tar.gz" 27 | ln -s qubes.files.tar.gz "${PKGS_DIR}/qubes.files" 28 | fi 29 | 30 | set -e 31 | 32 | # Remove local qubes packages signatures because pacman will only trust these 33 | # local packages if no signature is provided 34 | chroot_cmd --user=user /bin/sh -c 'if [ -n "$(ls pkgs/*.sig)" ] ; then rm pkgs/*.sig ; fi' 35 | 36 | # Generate custom repository metadata based on packages that are available 37 | # Repo Add need packages to be added in the right version number order as it only keeps the last entered package version 38 | chroot_cmd --user=user /bin/sh -c \ 39 | 'for pkg in `ls -v pkgs/*.pkg.tar.*`; do repo-add pkgs/qubes.db.tar.gz "$pkg"; done;' 40 | 41 | # Ensure pacman doesn't check for disk free space -- it doesn't work in chroots 42 | chroot_cmd sed "s/^ *CheckSpace/#CheckSpace/g" -i /etc/pacman.conf 43 | 44 | # Update archlinux keyring first so that Archlinux can be updated even after a long time 45 | chroot_cmd /bin/sh -c \ 46 | "http_proxy='${REPO_PROXY}' pacman -Sy --noconfirm --noprogressbar archlinux-keyring" 47 | 48 | # Now update system 49 | chroot_cmd /bin/sh -c \ 50 | "http_proxy='${REPO_PROXY}' pacman -Syu --noconfirm --noprogressbar" 51 | -------------------------------------------------------------------------------- /update-remote-repo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | name=vm-archlinux 4 | archlinux_directory=qubes-packages-mirror-repo/$name 5 | package_directory=$archlinux_directory/pkgs 6 | db=qubes.db 7 | 8 | echo "Signing all unsigned packages" 9 | 10 | for filename in $package_directory/*.pkg.tar.* ; do 11 | if ! [ -f "$filename.sig" ] ; then 12 | echo "Signing $filename" 13 | qubes-gpg-client-wrapper --detach-sign "$filename" > "$filename.sig" 14 | fi 15 | done 16 | 17 | sudo mount --bind $archlinux_directory chroot-$name/tmp/qubes-packages-mirror-repo 18 | 19 | echo "Generating 4.0 repository" 20 | sudo chroot chroot-$name su user -c 'cd /tmp/qubes-packages-mirror-repo; for pkg in `ls -v pkgs/qubes*.pkg.tar.*` ; do repo-add pkgs/'"$db"'.tar.gz "$pkg";done;' 21 | 22 | # Replace link with the real thing because it cannot be uploaded easily to repository 23 | rm $package_directory/$db 24 | cp $package_directory/$db.tar.gz $package_directory/$db 25 | 26 | # Sign the package database 27 | qubes-gpg-client-wrapper --detach-sign $package_directory/$db > $package_directory/$db.sig 28 | 29 | --------------------------------------------------------------------------------