--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Distribution=postmarketos
+
+[Content]
+Packages=
+ musl-utils
+ openssh-server
+ openssh-server-pam-systemd
+ postmarketos-base
+ postmarketos-base-systemd
+ util-linux
+
+# postmarketOS / Alpine Linux does not ship an unsigned shim
+ShimBootloader=none
"*.pkg.tar*",
"*.deb",
"*.ddeb",
+ "*.apk",
)
rpm = enum.auto()
deb = enum.auto()
pkg = enum.auto()
+ apk = enum.auto()
class DistributionInstaller:
debian = enum.auto()
kali = enum.auto()
ubuntu = enum.auto()
+ postmarketos = enum.auto()
arch = enum.auto()
opensuse = enum.auto()
mageia = enum.auto()
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+import shutil
+from collections.abc import Iterable
+
+from mkosi.config import Architecture, Config
+from mkosi.context import Context
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
+from mkosi.installer import PackageManager
+from mkosi.installer.apk import Apk, ApkRepository
+from mkosi.log import complete_step, die
+
+
+class Installer(DistributionInstaller):
+ @classmethod
+ def pretty_name(cls) -> str:
+ return "postmarketOS"
+
+ @classmethod
+ def filesystem(cls) -> str:
+ return "ext4"
+
+ @classmethod
+ def package_type(cls) -> PackageType:
+ return PackageType.apk
+
+ @classmethod
+ def default_release(cls) -> str:
+ return "edge"
+
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.postmarketos
+
+ @classmethod
+ def package_manager(cls, config: Config) -> type[PackageManager]:
+ return Apk
+
+ @classmethod
+ def setup(cls, context: Context) -> None:
+ # TODO: Create merged /usr manually for now until our upstream (Alpine Linux) supports it:
+ # https://gitlab.alpinelinux.org/alpine/aports/-/merge_requests/85504
+ for dir in ["lib", "bin", "sbin"]:
+ (context.root / "usr" / dir).mkdir(parents=True, exist_ok=True)
+ (context.root / dir).symlink_to(f"usr/{dir}")
+
+ with complete_step("Setting up postmarketOS keyring"):
+ # Create keys directory in sandbox
+ keys_dir = context.sandbox_tree / "etc/apk/keys"
+ keys_dir.mkdir(parents=True, exist_ok=True)
+
+ # Copy keys from various sources (if they exist)
+ for d in [
+ context.config.tools() / "usr/lib/apk/keys",
+ context.config.tools() / "usr/share/distribution-gpg-keys/alpine-linux",
+ context.config.tools() / "usr/share/distribution-gpg-keys/postmarketos",
+ ]:
+ if not d.exists():
+ continue
+ # Preserve/do not overwrite keys in keys_dir that already exist
+ for key in d.iterdir():
+ if key.is_file():
+ dest = keys_dir / key.name
+ if dest.exists():
+ continue
+ shutil.copy2(key, dest)
+
+ Apk.setup(context, list(cls.repositories(context)))
+
+ @classmethod
+ def install(cls, context: Context) -> None:
+ Apk.install(context, ["postmarketos-baselayout", "postmarketos-release"], apivfs=False)
+
+ @classmethod
+ def repositories(cls, context: Context) -> Iterable[ApkRepository]:
+ if context.config.release != "edge":
+ die(f"Only 'edge' release is currently supported, got '{context.config.release}'")
+
+ if context.config.local_mirror:
+ yield ApkRepository(url=context.config.local_mirror)
+ return
+
+ # Alpine repos
+ # Note: "testing" is enabled here because it's also enabled by default when pmbootstrap builds pmOS
+ # images, sometimes pmOS pkgs temporarily depend on things in testing.
+ for repo_name in ["main", "community", "testing"]:
+ yield ApkRepository(
+ url=f"https://dl-cdn.alpinelinux.org/alpine/{context.config.release}/{repo_name}"
+ )
+
+ # postmarketOS repos
+ mirror = context.config.mirror or "https://mirror.postmarketos.org/postmarketos"
+ subdir = "master" if context.config.release == "edge" else f"v{context.config.release}"
+
+ # systemd repo
+ url = f"{mirror}/extra-repos/systemd/{subdir}"
+ yield ApkRepository(url=url)
+
+ # main repo
+ url = f"{mirror}/{subdir}"
+ yield ApkRepository(url=url)
+
+ @classmethod
+ def architecture(cls, arch: Architecture) -> str:
+ a = {
+ Architecture.x86_64: "x86_64",
+ Architecture.arm64: "aarch64",
+ Architecture.arm: "armv7",
+ }.get(arch) # fmt: skip
+
+ if not a:
+ die(f"Architecture {a} is not supported by postmarketOS")
+
+ return a
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+import dataclasses
+import shutil
+from collections.abc import Sequence
+from pathlib import Path
+
+from mkosi.config import Config
+from mkosi.context import Context
+from mkosi.installer import PackageManager
+from mkosi.run import CompletedProcess, run, workdir
+from mkosi.util import _FILE, PathString
+
+
+@dataclasses.dataclass(frozen=True)
+class ApkRepository:
+ url: str
+
+
+class Apk(PackageManager):
+ @classmethod
+ def executable(cls, config: Config) -> str:
+ return "apk"
+
+ @classmethod
+ def subdir(cls, config: Config) -> Path:
+ return Path("apk")
+
+ @classmethod
+ def scripts(cls, context: Context) -> dict[str, list[PathString]]:
+ return {
+ "apk": cls.apivfs_script_cmd(context) + cls.env_cmd(context) + cls.cmd(context),
+ "mkosi-install": ["apk", "add", "--upgrade", "--cache-max-age", "999999999"],
+ "mkosi-upgrade": ["apk", "upgrade"],
+ "mkosi-remove": ["apk", "--remove", "del"],
+ "mkosi-reinstall": ["apk", "fix", "--reinstall"],
+ } # fmt: skip
+
+ @classmethod
+ def setup(cls, context: Context, repositories: Sequence[ApkRepository]) -> None:
+ config = context.sandbox_tree / "etc/apk/repositories"
+ if config.exists():
+ return
+
+ config.parent.mkdir(exist_ok=True, parents=True)
+
+ config.write_text("\n".join(repo.url for repo in repositories) + "\n")
+
+ @classmethod
+ def finalize_environment(cls, context: Context) -> dict[str, str]:
+ return super().finalize_environment(context) | {
+ # apk requires SHA1 support for signature verification, and this is disabled in the default
+ # crypto-policies for Fedora/RH/SuSE. This variable is set to re-enable SHA1 support on these
+ # distributions.
+ # Also see: https://gitlab.alpinelinux.org/alpine/apk-tools/-/issues/11139#note_542183
+ "OPENSSL_ENABLE_SHA1_SIGNATURES": "1",
+ }
+
+ @classmethod
+ def cmd(cls, context: Context) -> list[PathString]:
+ return [
+ "apk",
+ "--root", "/buildroot",
+ "--cache-dir", "/var/cache/apk",
+ "--arch", context.config.distribution.architecture(context.config.architecture),
+ "--no-interactive",
+ "--preserve-env",
+ "--cache-packages",
+ "--keys-dir", "/etc/apk/keys",
+ "--repositories-file", "/etc/apk/repositories",
+ *(["--allow-untrusted"] if not context.config.repository_key_check else []),
+ ] # fmt: skip
+
+ @classmethod
+ def invoke(
+ cls,
+ context: Context,
+ operation: str,
+ arguments: Sequence[str] = (),
+ *,
+ apivfs: bool = False,
+ stdout: _FILE = None,
+ ) -> CompletedProcess:
+ return run(
+ cls.cmd(context) + [operation, *arguments],
+ sandbox=cls.sandbox(context, apivfs=apivfs),
+ env=cls.finalize_environment(context),
+ stdout=stdout,
+ )
+
+ @classmethod
+ def install(
+ cls,
+ context: Context,
+ packages: Sequence[str],
+ *,
+ apivfs: bool = True,
+ allow_downgrade: bool = False,
+ ) -> None:
+ arguments = [
+ "--initdb",
+ "--upgrade",
+ # effectively disable refreshing the cache in this situation
+ "--cache-max-age", "999999999",
+ *packages,
+ ] # fmt: skip
+ cls.invoke(context, "add", arguments, apivfs=apivfs)
+
+ @classmethod
+ def remove(cls, context: Context, packages: Sequence[str]) -> None:
+ cls.invoke(context, "del", packages, apivfs=True)
+
+ @classmethod
+ def sync(cls, context: Context, force: bool) -> None:
+ # Initialize database first
+ cls.invoke(context, "add", ["--initdb"])
+ cls.invoke(context, "update", ["--update-cache"] if force else [])
+
+ @classmethod
+ def createrepo(cls, context: Context) -> None:
+ packages = [p.name for p in context.repository.glob("*.apk")]
+ if not packages:
+ return
+
+ # Move apk files to arch-specific directory
+ arch = context.config.distribution.architecture(context.config.architecture)
+ arch_dir = context.repository / arch
+ arch_dir.mkdir(exist_ok=True)
+ for package in packages:
+ (context.repository / package).rename(arch_dir / package)
+
+ # Generate temporary signing key using openssl
+ # This uses the same method as abuild-keygen, because this tool is not available on all distros
+ key_name = "mkosi@local-temp"
+ priv_key = context.workspace / f"{key_name}.rsa"
+ pub_key = context.workspace / f"{key_name}.rsa.pub"
+
+ if not priv_key.exists():
+ run(["openssl", "genrsa", "-out", str(priv_key), "2048"], env=cls.finalize_environment(context))
+ run(
+ ["openssl", "rsa", "-in", str(priv_key), "-pubout", "-out", str(pub_key)],
+ env=cls.finalize_environment(context),
+ )
+ keys_dir = context.sandbox_tree / "etc/apk/keys"
+ keys_dir.mkdir(parents=True, exist_ok=True)
+ shutil.copy2(pub_key, keys_dir / pub_key.name)
+
+ # Create index archive
+ run(
+ [
+ "apk",
+ "index",
+ "-o", "APKINDEX.tar.gz",
+ "--rewrite-arch", arch,
+ # Note: "allow-untrusted" because pkgs may be signed by another key that might not be
+ # available
+ "--allow-untrusted",
+ *packages,
+ ],
+ sandbox=context.sandbox(
+ options=[
+ "--bind", context.repository, workdir(context.repository),
+ "--chdir", workdir(arch_dir),
+ ]
+ ),
+ ) # fmt: skip
+
+ # Create and sign index signature file
+ # Note: The index signing stuff below was largely inspired by what abuild-sign and abuild-tar tools
+ # do on Alpine Linux. These tools are not always packages for other distros.
+ sig_file = arch_dir / f".SIGN.RSA.{pub_key.name}"
+ run(
+ [
+ "openssl",
+ "dgst",
+ "-sha1",
+ "-sign", str(priv_key),
+ "-out", str(sig_file),
+ str(arch_dir / "APKINDEX.tar.gz"),
+ ],
+ env=cls.finalize_environment(context),
+ ) # fmt: skip
+
+ # Create tar of signature, and strip EOF markers to allow concatenation with compressed index
+ temp_tar = context.workspace / "sig.tar"
+ with temp_tar.open("wb") as f:
+ run(
+ [
+ "tar", "-cf", "-",
+ "--format=posix",
+ "--owner=0",
+ "--group=0",
+ "--numeric-owner",
+ "-C", str(arch_dir),
+ sig_file.name,
+ ],
+ stdout=f,
+ ) # fmt: skip
+
+ tar_data = temp_tar.read_bytes()
+ while tar_data.endswith(b"\x00" * 512):
+ tar_data = tar_data[:-512]
+ temp_tar.write_bytes(tar_data)
+
+ # Prepend gzipped signature to original index
+ index_file = arch_dir / "APKINDEX.tar.gz"
+ temp_signed = context.workspace / "signed.tar.gz"
+ with temp_signed.open("wb") as out:
+ run(["gzip", "-n", "-9", "-c", str(temp_tar)], stdout=out)
+ out.write(index_file.read_bytes())
+
+ # Finally, overwrite the original index archive with the signed index archive
+ temp_signed.replace(index_file)
+
+ repos = context.sandbox_tree / "etc/apk/repositories"
+ local_repo = "file:///repository/"
+ if repos.exists():
+ content = repos.read_text()
+ if local_repo not in content:
+ with repos.open("a") as f:
+ f.write(f"{local_repo}\n")
+ else:
+ repos.write_text(f"{local_repo}\n")
+
+ cls.sync(context, force=True)
+
+ @classmethod
+ def keyring(cls, context: Context) -> None:
+ pass
* *Azure Linux*
+* *postmarketOS*
+
* *None* (**Requires the user to provide a pre-built rootfs**)
In theory, any distribution may be used on the host for building images
packages are defined and which packages are included in those default
tools trees:
-| | Fedora | CentOS | Debian | Kali | Ubuntu | Arch | openSUSE |
-|-------------------------|:------:|:------:|:------:|:----:|:------:|:----:|:--------:|
-| `acl` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `apt` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
-| `archlinux-keyring` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
-| `attr` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `bash` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `btrfs-progs` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `ca-certificates` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `coreutils` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `cpio` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `createrepo_c` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `curl` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `debian-keyring` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
-| `diffutils` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `distribution-gpg-keys` | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ |
-| `dnf` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `dosfstools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `e2fsprogs` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `edk2-ovmf` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `erofs-utils` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `findutils` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `git` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `grep` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `grub-tools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
-| `jq` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `kali-archive-keyring` | | | | ✓ | | | |
-| `kmod` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `less` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `mtools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `nano` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `opensc` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `openssh` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `openssl` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `pkcs11-provider` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `perf` | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ |
-| `sed` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `pacman` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
-| `p11-kit` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `policycoreutils` | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ |
-| `qemu` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `sbsigntools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `socat` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `squashfs-tools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `strace` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `swtpm` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `systemd` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `ukify` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `tar` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `ubuntu-keyring` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
-| `util-linux` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `virtiofsd` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `virt-firmware` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `xfsprogs` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `xz` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `zstd` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
-| `zypper` | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ |
+| | Fedora | CentOS | Debian | Kali | Ubuntu | Arch | openSUSE | postmarketOS |
+|-------------------------|:------:|:------:|:------:|:----:|:------:|:----:|:--------:|:------------:|
+| `acl` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `apt` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | |
+| `archlinux-keyring` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | |
+| `attr` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `bash` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `btrfs-progs` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `ca-certificates` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `coreutils` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `cpio` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `createrepo_c` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `curl` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `debian-keyring` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ |
+| `diffutils` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `distribution-gpg-keys` | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ |
+| `dnf` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `dosfstools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `e2fsprogs` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `edk2-ovmf` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `erofs-utils` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `findutils` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `git` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `grep` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `grub-tools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | |
+| `jq` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `kali-archive-keyring` | | | | ✓ | | | | |
+| `kmod` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `less` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `mtools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `nano` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `opensc` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `openssh` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `openssl` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `pkcs11-provider` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `perf` | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ | ✓ |
+| `sed` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `pacman` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ |
+| `p11-kit` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `policycoreutils` | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | ✓ |
+| `qemu` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `sbsigntools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `socat` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `squashfs-tools` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `strace` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `swtpm` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `systemd` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `ukify` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `tar` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `ubuntu-keyring` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | |
+| `util-linux` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `virtiofsd` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `virt-firmware` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `xfsprogs` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `xz` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `zstd` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| `zypper` | ✓ | | ✓ | ✓ | ✓ | ✓ | ✓ | |
# BUILDING MULTIPLE IMAGES
# REQUIREMENTS
mkosi is packaged for various distributions: Debian, Kali, Ubuntu, Arch
-Linux, Fedora Linux, OpenMandriva, Gentoo. Note that it has been a while
+Linux, Fedora Linux, OpenMandriva, Gentoo, postmarketOS. Note that it has been a while
since the last release and the packages shipped by distributions are
very out of date. We currently recommend running **mkosi** from git until a
new release happens.
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Distribution=postmarketos
+
+[Content]
+Packages=
+ kbd
+ util-linux-login
+ systemd-udevd
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Distribution=postmarketos
+
+[Content]
+Packages=
+ abuild
+ apk-tools
+ btrfs-progs
+ distribution-gpg-keys
+ erofs-utils
+ # NOTE: grub disabled because package trigger fails
+ # grub
+ libseccomp
+ p11-kit
+ sbsigntool
+ squashfs-tools
+ ukify
+ xz
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Distribution=postmarketos
+
+[Content]
+Packages=
+ git
+ man-db
+ man-pages
[Content]
Packages=
+ apk
apt
apt-utils
archlinux-keyring
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Distribution=postmarketos
+
+[Content]
+Packages=
+ apt
+ pacman
+ debian-archive-keyring
+ ubuntu-archive-keyring
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Distribution=postmarketos
+
+[Content]
+Packages=
+ mesa-dri-gallium
+ mesa-egl
+ mesa-gl
+ openssh-client
+ openssh-keygen
+ qemu-audio-alsa
+ qemu-audio-pa
+ qemu-audio-pipewire
+ qemu-audio-sdl
+ qemu-hw-display-virtio-gpu
+ qemu-hw-display-virtio-gpu-gl
+ qemu-hw-display-virtio-gpu-pci
+ qemu-hw-display-virtio-gpu-pci-gl
+ qemu-hw-display-virtio-vga
+ qemu-hw-display-virtio-vga-gl
+ qemu-hw-usb-host
+ qemu-hw-usb-redirect
+ qemu-ui-opengl
+ qemu-ui-sdl
+ qemu-modules
+ virtiofsd
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Architecture=arm64
+
+[Content]
+Packages=
+ aavmf
+ qemu-system-aarch64
+ qemu-system-arm
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Architecture=x86-64
+
+[Content]
+Packages=
+ ovmf
+ qemu-system-x86_64
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Distribution=postmarketos
+
+[Content]
+Packages=
+ agetty # required for *getty@ services
+ dbus-broker
+ iproute2
+ iputils
+ kmod # mkosi is incompatible with busybox depmod
+ linux-virt
+ systemd-boot
+ systemd-networkd
+ systemd-udevd
+ tpm2-tools