AI & ML

State of Linux Mobile 2026: PostmarketOS & F-Droid Updates

· 5 min read
SitePoint Premium
Stay Relevant and Grow Your Career in Tech
  • Premium Results
  • Publish articles on SitePoint
  • Daily curated jobs
  • Learning Paths
  • Discounts to dev tools
Start Free Trial

7 Day Free Trial. Cancel Anytime.

PostmarketOS now ships a generic mainline kernel and F-Droid is reforming its governance. The state of Linux mobile in 2026 looks different from twelve months ago. PostmarketOS has collapsed the per-device maintenance burden that historically throttled its device coverage. F-Droid has signaled governance and technical pipeline reforms that push alternative app distribution beyond a volunteer-only afterthought toward a more professionalized operation. PostmarketOS and F-Droid together form the most functional open-source mobile stack available, though "functional" still comes with caveats. For developers watching from the sidelines, the question is no longer whether these platforms exist, but whether they have crossed the threshold into practical utility. This article provides both an honest assessment of that question and a hands-on walkthrough: readers will leave with a working development environment, a deployable PWA, and a clear path to F-Droid distribution.

Table of Contents

PostmarketOS in 2026: The Generic Kernel Shift

What Changed: From Device-Specific to Generic Kernels

PostmarketOS historically maintained individual kernel builds for each supported device. Every phone or tablet required its own patchset, its own configuration, and its own maintenance volunteer, and this model scaled poorly as the device list outpaced volunteer bandwidth.

PostmarketOS has been moving toward generic mainline Linux kernels, aiming to replace per-device kernel builds with a single generic kernel image built from mainline Linux sources. Device Tree overlays and firmware packages handle device-specific behavior. Readers should verify the current kernel strategy against official PostmarketOS release notes before building toolchains around this assumption, as the timeline and scope of this transition may have shifted since this writing. In practical terms, one kernel image can boot across many devices, provided those devices have sufficient upstream driver support.

This shift aligns PostmarketOS with the same upstream-first philosophy that drives distributions like Fedora and Arch on the desktop. Fewer out-of-tree patches means fewer regressions during kernel upgrades, and the distribution inherits improvements from the thousands of developers contributing to mainline Linux without waiting for per-device volunteers to forward-port them.

Why This Matters for Developers

For anyone building software targeting PostmarketOS, the generic kernel model dramatically simplifies the testing matrix. Instead of wondering whether an app behaves differently across kernel versions tailored to different SoCs, developers can reasonably assume a more consistent kernel ABI across the supported device fleet. This makes CI pipelines more tractable and reduces the surface area for device-specific bugs.

Alignment with upstream Linux also means that modern kernel features, such as io_uring, eBPF improvements, and updated DRM/KMS graphics interfaces, arrive on PostmarketOS devices without the multi-month or multi-kernel-version lag that plagued the per-device model.

Alignment with upstream Linux also means that modern kernel features, such as io_uring, eBPF improvements, and updated DRM/KMS graphics interfaces, arrive on PostmarketOS devices without the multi-month or multi-kernel-version lag that plagued the per-device model. For developers building performance-sensitive applications or relying on recent kernel APIs, this is a substantive improvement.

Supported Devices and Current Limitations

PostmarketOS uses a tiered support system. Devices categorized under "main" receive the most testing and are expected to be functional for routine use. "Community" category devices work but may have rough edges or lack polish. Check the PostmarketOS devices wiki for current category names and device listings, as the nomenclature evolves over time.

Hardware gaps remain real. GPU acceleration is inconsistent across devices; many Qualcomm SoCs still rely on reverse-engineered Freedreno drivers that lag behind proprietary Adreno blobs in performance and feature coverage (see Phoronix Freedreno benchmarks for current deltas). Camera stacks are another weak point, as many mobile image signal processors lack mainline drivers entirely, leaving users with no camera or a degraded experience through libcamera. Cellular modem support varies: devices using Qualcomm modems with open firmware interfaces (like the PinePhone and PinePhone Pro, both using the Quectel EG25-G modem) work reasonably well, while others remain unreliable for voice calls or data connections.

The honest assessment: PostmarketOS in 2026 is a credible development target and an increasingly functional enthusiast platform. It is not yet a daily-driver replacement for Android or iOS for most users. Developers should treat it as a serious secondary target, not a primary deployment platform.

F-Droid Governance and Technical Evolution

Governance Reform Signals

F-Droid has signaled governance reform intentions, including movement toward a more open nomination process for board positions. Readers should verify current governance status at f-droid.org/en/news before relying on this for distribution decisions, as governance details may have changed since this writing. For developers who depend on F-Droid as a distribution channel, governance stability and transparency directly affect whether you can rely on the platform for long-term app distribution. Broadened leadership participation reduces single-point-of-failure risk in a project that distributes packages to the open-source Android and Linux mobile ecosystems.

Technical Roadmap Changes

Governance evolution has coincided with concrete technical roadmap changes. F-Droid's reproducible builds pipeline has received focused investment, aiming to make it straightforward for developers to verify that the APK distributed by F-Droid matches what the source code produces. The F-Droid team has targeted app review cycle times, a long-standing pain point, for improvement through better automation and clearer reviewer guidelines. The maintainers stabilized metadata standards and the F-Droid API, reducing the frequency of breaking changes that forced developers to update their listings.

Perhaps most relevant to this article's audience, community discussion has raised the possibility of F-Droid supporting non-Android targets such as Flatpak-based distribution for PostmarketOS, Mobian, and other Linux mobile distributions. Readers should check the F-Droid GitLab issue tracker for the current status of any such proposals before planning distribution strategies around them.

F-Droid vs. Traditional App Stores: 2026 Comparison

Google Play and the Apple App Store remain dominant in reach, tooling maturity, and monetization infrastructure. Flathub serves the desktop Linux ecosystem effectively but is not optimized for mobile form factors.

F-Droid occupies a distinct niche: it is the primary distribution channel for privacy-conscious users who want verifiable open-source software, and it is the only major store actively exploring expansion toward Linux mobile targets beyond Android. For developers building open-source tools, privacy-focused applications, or apps targeting the PostmarketOS and Mobian user base, F-Droid is not an alternative to Google Play so much as the correct distribution channel for the audience.

Setting Up a Linux Mobile Development Environment

Prerequisites and Toolchain Overview

The development workflow described here requires Node.js 22 LTS, React 19, and a machine capable of running QEMU with reasonable performance (8 GB host RAM minimum recommended, 16 GB preferred for comfortable emulation). PostmarketOS is Alpine-based and uses the apk package manager, which is important context if you need to install packages inside the VM. For F-Droid submission, fdroidserver (install via pip install fdroidserver) and familiarity with YAML metadata files are necessary. A working Docker installation is required for reproducible builds.

To scaffold the project, run the following and then install the required React version:

npm create vite@latest linux-mobile-pwa -- --template react
cd linux-mobile-pwa
npm install react@19 react-dom@19

Your package.json should include at minimum:

{
  "name": "linux-mobile-pwa",
  "private": true,
  "type": "module",
  "dependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "vite": "^5.0.0"
  }
}

Installing PostmarketOS in QEMU for Testing

PostmarketOS publishes prebuilt images suitable for QEMU. Because image filenames change with each release, retrieve the current download URL and SHA256 checksum from postmarketos.org/download rather than relying on hardcoded URLs. The following script illustrates the approach — update the PMOSURL variable with the current URL before running:

#!/bin/bash
set -euo pipefail

# IMPORTANT: Retrieve the current image URL and checksum from https://postmarketos.org/download
# The URL below is an EXAMPLE and will likely 404 as images are versioned.
PMOSIMAGE="postmarketos-qemu-amd64-phosh.qcow2"
PMOSURL="https://images.postmarketos.org/bpo/edge/qemu-amd64/phosh/${PMOSIMAGE}.xz"

# Download and decompress if not already present
if [ ! -f "$PMOSIMAGE" ]; then
  curl -fL -o "${PMOSIMAGE}.xz" "$PMOSURL"
  # Verify the download against the published checksum
  # Download the .sha256 file from the same directory on images.postmarketos.org
  curl -fL -o "${PMOSIMAGE}.xz.sha256" "${PMOSURL}.sha256"

  # Normalize: handle bare-hash files by appending the filename
  STORED=$(awk '{print $1}' "${PMOSIMAGE}.xz.sha256")
  echo "${STORED}  ${PMOSIMAGE}.xz" | sha256sum -c - || {
    echo "Checksum verification failed!"; exit 1;
  }

  xz -d "${PMOSIMAGE}.xz"
fi

# Platform-specific acceleration
# Linux uses KVM; macOS uses HVF; Windows users should set ACCEL="-accel whpx"
if [[ "$(uname)" == "Darwin" ]]; then
  ACCEL="-accel hvf"
  CPU_FLAG=""
elif [[ "$(uname)" == "Linux" ]]; then
  ACCEL="-enable-kvm"
  CPU_FLAG="-cpu host"
else
  ACCEL=""  # Windows users: set to "-accel whpx" or "-accel hax" if available
  CPU_FLAG=""
fi

# Launch QEMU with port forwarding for SSH and HTTP access
# 8 GB host RAM is recommended; the VM is allocated 2 GB by default.
# Increase -m 4096 for better Phosh performance.
qemu-system-x86_64 \
  -m 2048 \
  ${CPU_FLAG:+"$CPU_FLAG"} \
  "$ACCEL" \
  -vga virtio \
  -display gtk \
  -drive file="$PMOSIMAGE",format=qcow2 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
  -device virtio-net-pci,netdev=net0

Port 2222 on the host maps to SSH inside the VM, and port 8080 forwards to the guest's HTTP port, enabling quick testing of web applications served from within PostmarketOS.

Building a Mobile-Ready PWA with React

Progressive Web Apps are the pragmatic entry point for Linux mobile development. They require no Gtk or Qt knowledge, run in any modern browser, and work across both Phosh (GNOME-based) and Plasma Mobile shell environments. The key constraint is screen size: PostmarketOS devices typically present viewports between 360px and 420px wide.

import { useState, useEffect } from 'react';

const MOBILE_MAX_WIDTH = 420;

function useLinuxMobile() {
  const [isLinuxMobile, setIsLinuxMobile] = useState(false);

  useEffect(() => {
    function evaluate() {
      const ua = navigator.userAgent.toLowerCase();
      const isLinux = ua.includes('linux') && !ua.includes('android');
      const isNarrow = window.innerWidth <= MOBILE_MAX_WIDTH;
      setIsLinuxMobile(isLinux && isNarrow);
    }

    evaluate();
    window.addEventListener('resize', evaluate);
    return () => window.removeEventListener('resize', evaluate);
  }, []);

  return isLinuxMobile;
}

export default function MobileApp() {
  const isLinuxMobile = useLinuxMobile();

  return (
    <div style={{
      maxWidth: '420px',
      margin: '0 auto',
      padding: '1rem',
      containerType: 'inline-size',
    }}>
      <header>
        <h1 style={{ fontSize: 'clamp(1.2rem, 5cqi, 1.8rem)' }}>
          Linux Mobile PWA
        </h1>
        {isLinuxMobile && (
          <p style={{ color: '#4caf50', fontSize: '0.85rem' }}>
            Detected likely Linux mobile environment
          </p>
        )}
      </header>
      <main>
        <p>Responsive content targeting 360–420px viewports.</p>
        <nav style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
          <button style={{ padding: '0.75rem', fontSize: '1rem' }}>Action One</button>
          <button style={{ padding: '0.75rem', fontSize: '1rem' }}>Action Two</button>
        </nav>
      </main>
    </div>
  );
}

The useLinuxMobile hook attempts to differentiate Linux mobile environments from Android (which also reports "Linux" in the user agent) by checking for the absence of the "android" string combined with a narrow viewport. Important caveat: this heuristic is imprecise. It will return true for any non-Android Linux browser at a viewport width of 420px or less, including desktop Firefox resized to a narrow window. Treat it as a progressive enhancement hint, not a reliable platform detection mechanism. The hook re-evaluates on window resize, so orientation changes and split-view adjustments are reflected. CSS container queries via cqi units ensure typography scales with the container rather than the viewport, which behaves more predictably when the app is embedded or used in split-view on convergent devices. Note that cqi units reference the nearest ancestor with container-type set — in this case, the parent <div>.

Adding Offline-First Capability with a Service Worker

Offline-first design is not optional on Linux mobile. Modem support remains inconsistent, and many users are data-conscious. The following build script uses Workbox to generate a service worker with a cache-first strategy for static assets and a network-first strategy for API calls.

If your project uses "type": "module" in package.json (as in the Vite scaffold above), use the ESM import syntax. Otherwise, use require():

// ESM version (for "type": "module" projects)
import { generateSW } from 'workbox-build';

// CJS version (for CommonJS projects):
// const { generateSW } = require('workbox-build');

async function buildServiceWorker() {
  const { count, size } = await generateSW({
    globDirectory: './dist',
    globPatterns: ['**/*.{html,js,css,png,svg,woff2}'],
    swDest: './dist/sw.js',
    runtimeCaching: [
      {
        urlPattern: /^https:\/\/api\./,
        handler: 'NetworkFirst',
        options: {
          cacheName: 'api-cache',
          networkTimeoutSeconds: 3,
          plugins: [
            {
              // ExpirationPlugin — limits cache size and age
              maxEntries: 50,
              maxAgeSeconds: 86400,
            },
          ],
        },
      },
    ],
    // WARNING: skipWaiting + clientsClaim immediately replaces the running
    // service worker in ALL open tabs without waiting for navigation.
    // If the new SW is broken, all tabs receive broken cached content.
    // Only enable after confirming the new SW is production-ready.
    skipWaiting: false,  // set true only for verified hotfix deployments
    clientsClaim: false,
  });
  console.log(`Generated SW: ${count} files precached, ${(size / 1024).toFixed(1)} KB`);
}

buildServiceWorker().catch(err => {
  console.error(err);
  process.exit(1);
});

The three-second network timeout for API calls is deliberately aggressive, reflecting the reality that cellular connections on Linux mobile devices may hang rather than fail cleanly. Pin workbox-build to a specific version in your package.json (e.g., "workbox-build": "^7.0.0") for reproducible builds.

Packaging and Distributing Your App via F-Droid

Understanding F-Droid's Metadata Format

F-Droid listings are driven by YAML metadata files stored in the fdroiddata repository. Each file declares the app's identity, license, build instructions, and any anti-features:

Categories:
  - System
  - Internet
License: GPL-3.0-only
AuthorName: Your Name
AuthorEmail: [email protected]
SourceCode: https://github.com/yourname/linux-mobile-pwa
IssueTracker: https://github.com/yourname/linux-mobile-pwa/issues

AutoName: Linux Mobile PWA

RepoType: git
Repo: https://github.com/yourname/linux-mobile-pwa.git

Builds:
  - versionName: 1.0.0
    versionCode: 1
    commit: v1.0.0
    subdir: app
    gradle:
      - yes
    prebuild:
      - npm ci
      - npm run build

AutoUpdateMode: Version
UpdateCheckMode: Tags
CurrentVersion: 1.0.0
CurrentVersionCode: 1

The AntiFeatures field is omitted here because the example contains none, but developers must declare features like NonFreeNet, Tracking, or NonFreeAssets if applicable. Omitting a required anti-feature declaration is a common rejection reason.

Reproducible Builds and Verification

F-Droid's build server compiles your app from source, then compares the unsigned artifact contents (not the signature itself, since signatures are per-signer and inherently non-reproducible) to the APK you uploaded. For this to work, the Dockerfile must produce a deterministic build environment:

FROM node:22.4.0-bookworm-slim

# Install JDK
RUN apt-get update && apt-get install -y --no-install-recommends \
    openjdk-17-jdk-headless \
    curl \
    unzip \
    && rm -rf /var/lib/apt/lists/*

# Install Android command-line tools (android-sdk is NOT a Debian package)
ENV ANDROID_HOME=/opt/android-sdk
# PIN: verify this SHA256 against https://developer.android.com/studio before updating
ARG CMDTOOLS_ZIP=commandlinetools-linux-11076708_latest.zip
ARG CMDTOOLS_SHA256=2d2d50857e4eb553af5a6dc3ad507a17adf43d115264b1afc116f95c92e5e258

RUN mkdir -p ${ANDROID_HOME}/cmdline-tools && \
    curl -fLo /tmp/cmdtools.zip \
      "https://dl.google.com/android/repository/${CMDTOOLS_ZIP}" && \
    echo "${CMDTOOLS_SHA256}  /tmp/cmdtools.zip" | sha256sum -c - && \
    unzip /tmp/cmdtools.zip -d ${ANDROID_HOME}/cmdline-tools && \
    mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest && \
    rm /tmp/cmdtools.zip

ENV PATH="${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${PATH}"

# Accept SDK licenses non-interactively, then install build tools
RUN yes | sdkmanager --licenses && \
    sdkmanager "build-tools;34.0.0" "platforms;android-34"

WORKDIR /app
COPY package*.json ./
# NOTE: --ignore-scripts is appropriate only if your dependencies do not require
# install-time compilation (native addons, etc.). Verify that npm ci and
# npm ci --ignore-scripts produce identical node_modules for your dependency tree.
RUN npm ci --ignore-scripts
COPY . .
RUN chmod +x gradlew
RUN npm run build && ./gradlew assembleRelease

Pinning Node.js, the JDK version, Android SDK build tools, and using npm ci (which respects the lockfile exactly) are all essential for reproducibility. Floating dependency versions are the most frequent cause of build mismatches. Note that npm ci requires a package-lock.json to be present — ensure it is committed to your repository.

Submitting to F-Droid: Step by Step

The submission process involves forking the fdroiddata repository on GitLab, adding the metadata YAML file, and opening a merge request. Reviewers verify that the license declaration is correct, the metadata parses cleanly, and the build reproduces. Common rejection reasons include missing license declarations, undeclared anti-features, and builds that fail to reproduce.

Review cycle times vary and depend on the complexity of the build and current reviewer availability. Simple apps with clean metadata may receive initial feedback within days, but complex builds can sit in the queue for weeks or longer. Check the F-Droid build status dashboard and community forums for current queue depth before planning release timelines.

Testing Across the Linux Mobile Ecosystem

Device Testing vs. Emulator Testing

QEMU is sufficient for layout testing, service worker verification, and basic functional testing. It falls short for GPU-accelerated rendering performance, camera integration, and modem behavior. For those scenarios, physical hardware is necessary. Affordable and well-supported options include the PinePhone Pro, OnePlus 6T, and Poco F1, all of which have community-category or better support in PostmarketOS.

Automated Testing with Node.js

Puppeteer enables headless browser testing at mobile viewport sizes, simulating the constraints of a Phosh environment:

import puppeteer from 'puppeteer';
// Requires puppeteer >=22. Pin version in package.json: "puppeteer": "^22.0.0"

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();

  try {
    for (const width of [360, 390, 420]) {
      await page.setViewport({ width, height: 720, deviceScaleFactor: 2 });
      await page.goto('http://localhost:3000', {
        waitUntil: 'networkidle0',
        timeout: 10000,
      });

      await page.waitForSelector('h1', { timeout: 5000 });
      const title = await page.$eval('h1', el => el.textContent);
      const overflowX = await page.evaluate(
        () => document.documentElement.scrollWidth > document.documentElement.clientWidth
      );

      console.log(`[${new Date().toISOString()}] [${width}px] Title: "${title}" | Overflow: ${overflowX}`);
      await page.screenshot({ path: `test-${width}px.png` });
    }
  } finally {
    await browser.close();
  }

  console.log('Mobile viewport tests complete.');
})();

This script catches horizontal overflow issues, a common problem when desktop-oriented layouts are served to narrow viewports, and produces screenshots for visual review.

Linux Mobile Developer Readiness Checklist

Use this checklist to track progress from initial setup through submission. Each item corresponds to a concrete step covered in this article.

  • PostmarketOS QEMU image downloaded and booting — Verify checksum with sha256sum -c, then confirm SSH access on port 2222 and HTTP on 8080.
  • Node.js 22 LTS and React 19 project initialized — Confirm with node -v and check package.json for React 19.
  • Have you verified responsive layout at both 360px and 420px? Use Puppeteer screenshots or browser dev tools to confirm no horizontal overflow.
  • Service worker configured with offline-first caching — Test by disabling the network in dev tools after initial load.
  • Run fdroid lint metadata/your.app.id.yml to catch syntax and schema errors before submitting your metadata YAML.
  • Build the Dockerfile twice. Diff the output artifacts. If they diverge, your reproducible build is broken.
  • App submitted to F-Droid (or staged for submission) — Fork fdroiddata, add metadata, open merge request.
  • If you have physical hardware, test on it. If not, QEMU with GPU passthrough covers most cases. Note which hardware gaps (camera, modem) remain untestable in your setup.
  • Phosh and Plasma Mobile shell UX reviewed — Check that touch targets are minimum 44px and navigation is thumb-reachable.
  • Bookmark the F-Droid build status page for your app ID and check it after submission.

Is Linux Mobile Finally Viable for Developers? An Honest Assessment

What Works Today

PWAs and lightweight web applications run well on PostmarketOS devices with current browser support. Terminal tools and CLI-based applications work as expected given the underlying Linux distribution. Privacy-focused distribution via F-Droid reaches an established user base (check F-Droid's public metrics for current install counts). For hobbyist projects, internal tools, and developer utilities, the platform is functional today.

What's Still Missing

The native app ecosystem remains thin. GTK4 and Qt6 mobile adaptations exist but lack the breadth of Android or iOS widget libraries. Hardware acceleration is inconsistent, making graphics-intensive applications unreliable. Cellular modem support, while improving, does not yet meet the reliability bar for primary-phone use across more than a handful of devices.

What Developers Gain by Shipping Now

Developers who build for Linux mobile now claim package names and establish presence in an uncrowded space before it gets noisy.

Developers who build for Linux mobile now claim package names and establish presence in an uncrowded space before it gets noisy. Early adopters get direct feedback loops with engaged, technical users who file detailed bug reports. The EU Digital Markets Act requires Apple to permit alternative app installation on iOS in the EU (enforcement began in March 2024, with ongoing compliance disputes into 2025), which is expanding the conversation around sideloading and alternative stores, though F-Droid's specific benefit from this remains speculative. Perhaps most concretely, convergent Linux applications, those that automatically adapt their UI between mobile and desktop form factors using patterns promoted by Plasma Mobile and libhandy/libadwaita, let a single codebase serve multiple deployment targets. For teams already targeting desktop Linux, the marginal cost of supporting Linux mobile drops close to zero.

Your Next Steps

The development workflow outlined here, from QEMU setup through F-Droid submission, works today. Clone the example project, run through the checklist, and ship something.

PostmarketOS's mainline kernel trajectory and F-Droid's governance maturation represent real, measurable momentum. The development workflow outlined here, from QEMU setup through F-Droid submission, works today. Clone the example project, run through the checklist, and ship something. Keep an eye on F-Droid's evolving distribution target support and PostmarketOS's expanding device list as both projects continue to mature.