-
Notifications
You must be signed in to change notification settings - Fork 205
Home
Welcome to the docker-lineage-cicd wiki!
A fair number of dependencies is needed to build LineageOS, plus a Linux system (and a discrete knowledge of it). With Docker we give you a minimal Linux build system with all the tools and scripts already integrated, easing considerably the creation of your own LineageOS build.
Moreover Docker runs also on Microsoft Windows and Mac OS, which means that LineageOS can be built on such platforms without requiring a dual boot system or a manual set up of a Virtual Machine.
The official Docker guides are well-written:
- Linux (Ubuntu, Debian, CentOS and Fedora are officially supported)
- Windows 10/Windows Server 2016 64bit
- Mac OS El Capitan 10.11 or newer
Life is considerably easier if you setup Docker to allow execution by non-root users: see 'Run the Docker daemon as a non-root user'
If your Windows or Mac system doesn't satisfy the requirements (or if you have Oracle VirtualBox installed, you can use Docker Toolbox. Docker Toolbox is not described in this guide, but it should be very similar to the standard Docker installation.
Once you can run the hello-world image you're ready to start!
Docker will produce the following files in the zips directory:
- the main ROM zip file e.g.
lineage-20.0-20230702-microG-<device-name>.zip. This file can be flashed from recovery as described in the next section - a custom recovery image (e.g.
lineage-20.0-20230702-microG-<device-name>-recovery.imgorlineage-20.0-20230702-microG-<device-name>-boot.img) and any other images needed or mentioned in the LineageOS installation instructions;- if the
ZIP_UP_IMAGESenvironment variable is settrue, these images will be zipped up into an-images.zipfile e.g.lineage-20.0-20230702-microG-<device-name>-images.zip - else, if the
MAKE_IMG_ZIP_FILEenvironment variable is settruethe images are zipped into a flashable...-img.zipfile (e.g.lineage-20.0-20230702-microG-<device-name>-img.zip) which can be installed usingfastboot flashorfastboot update
- if the
Docker can build the following ROMs (See Examples for more details)
- LineageOS for microG: set
WITH_GMS=trueand use a local manifest pointing to theandroid_vendor_partner_gmsrepository - 'Plain' LineageOS: set
WITH_GMS=false -
IodéOS: use the Docker image with the tag
:pf-build-iodeOSand IodéOS branch names (see https://gitlab.iode.tech/os/public/manifests/android/-/branches).
Before you start, make sure you have the latest version of our Docker image:
docker pull lineageos4microg/docker-lineage-cicd
The requirements for building LineageOS for MicroG are roughly the same as for building LineageOS:
-
A relatively recent x86_64 computer:
- Linux, macOS, or Windows - these instructions are only tested using Ubuntu 20.04 LTS, so we recommend going with that.
- A reasonable amount of RAM (16 GB to build up to lineage-17.1, 32 GB or more for lineage-18.1 and up). The less RAM you have, the longer the build will take. Enabling ZRAM can be helpful. If builds fail because of lack of memory, you can sometimes get over the problem by increasing the amount of swap, but this will be at the expense of slower build times.
- A reasonable amount of Storage (~300 GB for lineage-18.1 and up). You might require more free space for enabling ccache, building for multiple devices, or if you choose to mirror the LineageOS sources (see below). Using SSDs results in considerably faster build times than traditional hard drives.
-
A decent internet connection and reliable electricity. :)
-
Some familiarity with basic Android operation and terminology. It may be useful to know some basic command line concepts such as cd, which stands for “change directory”, the concept of directory hierarchies, and that in Linux they are separated by /, etc.
This Docker image contains a great number of settings, to allow you to fully customize your LineageOS build. Here you can find all of them, with the default values between the brackets.
TL;DR - go to the Examples
The two fundamental settings are:
-
BRANCH_NAME (lineage-16.0): LineageOS branch, see the branch list here (multiple comma-separated branches can be specified) -
DEVICE_LIST: comma-separated list of devices to build
Running a build with only these two set will create a ZIP file almost identical to the LineageOS official builds, just signed with the test keys.
Earlier versions of the Docker image allowed building multiple branches in a single call to docker run, using DEVICE_LIST_<BRANCH_NAME> to specify the list of devices for each specific branch. This functionality added unnecessary complexity, and is no longer supported: if you need to build multiple branches, call docker run once for each branch.
To include microG (or possibly the actual Google Mobile Services) in your build, LineageOS expects certain Makefiles in vendor/partner_gms and variable WITH_GMS set to true.
This repo contains the common packages included for official lineageos4microg builds. To include it in your build, create an XML (the name is irrelevant, as long as it ends with .xml) in the /home/user/manifests folder with this content:
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<project path="vendor/partner_gms" name="lineageos4microg/android_vendor_partner_gms" remote="github" revision="master" />
</manifest>If you wish to add other apps to your ROM, you can include a repository with source code or prebuilt APKs. For prebuilt apks, see the android_vendor_partner_gms repository for examples on how the Android.mk file should look like.
Include the repo with another manifest file like this:
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<project name="your-github-user/your-repo" path="prebuilts/my-custom-apps" remote="github" revision="master" />
</manifest>And when starting the build, set the CUSTOM_PACKAGES variable to a list of app names (defined by LOCAL_MODULE in Android.mk) separated by spaces.
I you need to apply patches to source code (e.g. because changes are needed which have not been merged to the repo or branch specifide in the build manifest), the you can apply these in one of the userscripts (i.e. either before.sh or pre-build.sh. The project uses before.sh).
The following example code shows how to
- revert existing commits in project repos
- fetch and cherry-pick commits from other branches
- apply a patch file
#!/bin/sh
# do we need the `yoshino-common` patches?
if [ -d "device/sony/yoshino-common" ]; then
echo "applying Yoshinopatches"
cd hardware/interfaces
echo "reverting commit 7ad5797272c40c2b83b0df5a57a0f248a210091b in hardware/interfaces"
git revert 7ad5797272c40c2b83b0df5a57a0f248a210091b
cd ../..
cd kernel/configs/
echo "reverting commit 3610907a2b8fd449665d30b09085234e5eb04dd9 in kernel/configs"
git revert 3610907a2b8fd449665d30b09085234e5eb04dd9
cd ../..
cd device/sony/yoshino-common
echo "cherry-picking commit from /aomsin2526/android_device_sony_yoshino-common"
git fetch "https://github.com/aomsin2526/android_device_sony_yoshino-common" lineage-21-qpr3 && git cherry-pick 5cacc64423de10497e3463b0032b0525c2dd3d19
cd ../../..
fi
echo "applying PI patch in system/core"
cd system/core
git reset --hard
wget https://git.disroot.org/flame-0/android_vendor_extra/raw/branch/main/patches/system_core/0001-Pass-SafetyNet.patch
git apply 0001-Pass-SafetyNet.patch
cd ../../That code is pretty much what the project uses to make our 'unofficial' builds for Sony Yoshino devices, although the final section - applying the PlayIntegrity patch - is no longer needed, as that patch is now applied by the Docker image (unless disabled using the APPLY_PI_PATCH environment variable)
You may wish / need to use git reset --hard and git clean - either in your before.sh / pre-build.sh, or in a post-build.sh` - to ensure that the source tree is in a 'known \ good' state before applying your patch or after cmpeting your build
Please read this post in the microG GmsCore wiki for an explanation of Signature spoofing. Until February 2025, official LineageOS ROMs did not support signature spoofing. Before then LineageOS had refused requests to support sgnature spoofing, because
it isn't our place to lie about security features.
For LineageOS for microG to work, we had to patch the LineageOS source code to allow microG GmsCore to spoof the existence of the official Play Services to applications calling Google APIs. The SIGNATURE_SPOOFING environment variable was used when building our ROMs, so that the correct patches could be applied to the LineageOS sources.
In February 2025, LineageOS added support for signature spoofing in LineageOS versions 18.1, 19.1, 20.0 and 21.0. This support only allows microG to spoof its signature; no other apps are allowed to do so. This 'restricted' signature spoofing is enough for LineageOS for microG builds to work, so we did not create patches for the lineage-22.1 branch, and the patches for the 18.1, 19.1, 20.0 versions are not used, not maintained, and - since Google made changes to the signature checking code in December 2024 - will probably no longer work.
LineageOS did not make any changes in the 17.1 branch to add support for signature spoofing, so to make a 17.1 build, you will need to apply the changes to AndroidManifest.xml and strings.xml from the Android Q LOS 17.1 branch-specific patch. You do not need to apply the other changes in that patch. (See this issue, and all it's comments for more information about this)
If anyone wanted to try to use the other patches, the following information, now out of date, may be useful:
Outdated information
Two custom signature spoofing patches are provided:
- "Original" patches
- Restricted patches
With the "original" patch the FAKE_SIGNATURE permission can be granted to any user app: while it may seem handy, this is considered dangerous by a great number of people, as the user could accidentally give this permission to rogue apps.
A more strict option is the restricted patch, where the FAKE_SIGNATURE permission can be obtained only by privileged system apps, embedded in the ROM during the build process.
The custom signature spoofing patch can be optionally included with:
-
SIGNATURE_SPOOFING (no):yesto use the original patch,restrictedfor the restricted one,nofor none of them and to default to built-in signature spoofing.
If in doubt, use restricted: note that packages that requires the
FAKE_SIGNATURE permission must be included in the build as system apps
(e.g. as part of GMS or CUSTOM_PACKAGES)
These patches are currently disabled for LineageOS 21 entirely. If you have an use case which requires the use of custom patches on 21, please open an issue.
End of outdated information
To help improve the Play Integrity performance of our ROMs, we have chosen to apply the patch from here in system/core. Builds made with this patch allow at least some apps - including the Nationwide UK Banking app - to run, when they would not run in builds without the patch. See issue #784 for more information.
If you wish to build without this patch, then build with the APPLY_PI_PATCH environment variable set to false.
Some proprietary binary files are needed to create a LineageOS build: these are components that
- are not open source, so cannot be built from source for our builds
- are device-specific: they are often low-level libraries drivers for hardware components
- have to be extracted from the device-specific software and firmware shipped by the manufacturer
- are often referred to as 'blobs'
The extraction process is complicated and error prone. The easiest way to include them in builds of devices that are - or have been - officially supported by LineageOS, is to use the versions which are stored in TheMuppets GitHub and GitLab repositories. These repositories are used in our builds and in official LineageOS builds, but are not included in the LineageOS repositories for legal reasons.
Using TheMuppets repositories is easy, and is enabled by default: the INCLUDE_PROPRIETARY variable is set 'true' in the Dockerfile
If you want to try extracting them yourself - perhaps to build for a device not supported by LineageOS - then LineageOS provide documentation on
If you don't want or need to use TheMuppets repositories, set INCLUDE_PROPRIETARY to false and provide a manifest pointing to a repository containing the blobs you will use instead (see Examples).
To enable OTA for you builds, you need to run a server that speaks the protocol understood by the LineageOS updater app and provide the URL to this server as OTA_URL variable for the build.
One implementation is LineageOTA, which is also available as Docker image. Follow these steps to prepare your builds for OTA:
- Run the Docker image
julianxhokaxhiu/lineageota- Port 80 exposed to the internet (might want to add an HTTPS reverse proxy)
- The
/srv/zipsdirectory/volume of the CICD image mounted at/var/www/html/builds/full(can be read-only)
- Set environment variables when building
-
ZIP_SUBDIRtofalse -
OTA_URLto the address of the OTA server, with/apiappended
-
If you don't setup a OTA server you won't be able to update the device from the updater app (but you can still update it manually with the recovery of course).
By default, builds are signed with the Android test keys. If you want to sign your builds with your own keys (highly recommended):
-
SIGN_BUILDS (false): set totrueto sign the builds with the keys contained in/srv/keys; if no keys are present, a new set will be generated
Some of the the steps in the build process (e.g repo sync, mka) can take a long time to complete. When working on a build, it may be desirable to skip some of the steps. The following environment variables (and their default values) control whether or not each step is performed
# variables to control whether or not tasks are implemented
ENV INIT_MIRROR true
ENV SYNC_MIRROR true
ENV RESET_VENDOR_UNDO_PATCHES true
ENV CALL_REPO_INIT true
ENV CALL_REPO_SYNC true
ENV CALL_GIT_LFS_PULL false
ENV APPLY_PATCHES true
ENV PREPARE_BUILD_ENVIRONMENT true
ENV CALL_BREAKFAST true
ENV CALL_MKA true
ENV ZIP_UP_IMAGES false
ENV MAKE_IMG_ZIP_FILE false
ENV APPLY_PI_PATCH true
To switch an operation, change the default value of the the variable in a -e clause in the docker run command e.g.
-e "CALL_REPO-SYNC=false" \
The ZIP_UP_IMAGES and MAKE_IMG_ZIP_FILE variables control how the .img files created by the buid are handled:
- by default, the
imgfiles are copied - unzipped - to thezipsdirectory - if
ZIP_UP_IMAGESis settrue, the images are zipped and the resulting...images.zipis copied to thezipsdirectory - if
MAKE_IMG_ZIP_FILEis settrue, a flashsable...-img.zipfile is created, which can be installed usingfastboot flashorfastboot update
Other useful settings are:
-
CCACHE_SIZE (50G): change this if you want to give more (or less) space to ccache -
RELEASE_TYPE (UNOFFICIAL): change the release type of your builds -
BUILD_TYPE (userdebug): type of your builds, see Android docs -
BUILD_OVERLAY (false): normally each build is done on the source tree, then the tree is cleaned withmka clean. If you want to be sure that each build is isolated from the others, setBUILD_OVERLAYtotrue(longer build time). Requires--cap-add=SYS_ADMIN. (As the time of writing - 27 January 2025 - this setting does not work: settingBUILD_OVERLAY=truewill cause the build to fail with an error message). -
LOCAL_MIRROR (false): change this totrueif you want to create a local mirror of the LineageOS source (> 200 GB) -
CRONTAB_TIME (now): instead of building immediately and exit, build at the specified time (uses standard cron format) -
ZIP_SUBDIR (true): Move the resulting zips to $ZIP_DIR/$codename instead of $ZIP_DIR/ -
PARALLEL_JOBS: Limit the number of parallel jobs to run (-jforrepo syncandmka). By default, the build system should match the number of parallel jobs to the number of cpu cores on your machine. Reducing this number can help keeping it responsive for other tasks. -
RETRY_FETCHES: Set the number of retries for the fetch duringrepo sync. By default, this value is unset (defaultrepo syncretry behavior). Positive values greater than 0 are allowed.
The full list of settings, including the less interesting ones not mentioned in this guide, can be found in the Dockerfile.
You also have to provide Docker some volumes, where it'll store the source, the resulting builds, the cache and so on. The volumes are:
-
/srv/src, for the LineageOS sources -
/srv/zips, for the output builds -
/srv/logs, for the output logs -
/srv/ccache, for the ccache -
/srv/local_manifests, for custom manifests (optional) -
/srv/userscripts, for the user scripts (optional)
When SIGN_BUILDS is true
-
/srv/keys, for the signing keys
When BUILD_OVERLAY is true
-
/srv/tmp, for temporary files
When LOCAL_MIRROR is true:
-
/srv/mirror, for the LineageOS mirror
These volumes do not need to be in the same directory tree: you specify the directories that Docker will use for these volumes in the docker run ... command.
All these examples use the directory /home/user/work as the base directory for the volumes. Amend the commands as required to fit your working setup.
- building the
lineage-22.1branch - see https://github.com/LineageOS/android/branches for possible options -
WITH_GMS=trueto include the makefiles and components from theandroid_vendor_partner_gmsrepository - local manifest pointing to the
android_vendor_partner_gmsrepository
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<project path="vendor/partner_gms" name="lineageos4microg/android_vendor_partner_gms" remote="github" revision="master" />
</manifest>-
INCLUDE_PROPRIETARY=trueto use the proprietary vendor blobs fromTheMuppetsGitHub repos. This is not really needed in the command as it is the default value set inDockerfile - Sony Xperia 1 III codename: pdx215
docker run \
-e "BRANCH_NAME=lineage-22.1" \
-e "DEVICE_LIST=pdx215" \
-e "WITH_GMS=true" \
-e "INCLUDE_PROPRIETARY=true" \
-v "/home/user/lineage:/srv/src" \
-v "/home/user/zips:/srv/zips" \
-v "/home/user/logs:/srv/logs" \
-v "/home/user/cache:/srv/ccache" \
lineageos4microg/docker-lineage-cicd- to build for more than one device, add the device names, separated by commas, to the
DEVICE_LISTline e.g.
-e "DEVICE_LIST=pdx215,pdx234,pdx237" \
- as for LineageOS for microG except
-
WITH_GMS=false. This is not really needed in the command as it is the default value set inDockerfile - don't need the local manifest pointing to the
android_vendor_partner_gmsrepository
docker run \
-e "BRANCH_NAME=lineage-22.1" \
-e "DEVICE_LIST=pdx215" \
-e "WITH_GMS=false" \
-v "/home/user/lineage:/srv/src" \
-v "/home/user/zips:/srv/zips" \
-v "/home/user/logs:/srv/logs" \
-v "/home/user/cache:/srv/ccache" \
lineageos4microg/docker-lineage-cicd- as for LineageOS, but use the
:pf-build-iodeOStag - use the IodéOS branches (see https://gitlab.iode.tech/os/public/manifests/android/-/branches).
v5is Android 14 / LineageOS 21.0. (At the time of writing - January 2025 - that is the latest official branch of IodéOS) - this example uses
/home/user/iodefor thesrcvolume, but as noted above, any directory can be used - building with
WITH_GMS=false(the default) is usually fine:WITH_GMSis not needed to pull in the microG, F-Droid and other components, as they are included in the IodéOS sources and manifests. Some devices useWITH_GMSto change the amount of space reserved for different partitions (see e.g. here or here). If your build fails with e.g. errors in partition sizes, settingWITH_GMS=truemay allow it to succeed. An alternative approach to fixing such errors is to set values explicitly. These can be configured for e.g.BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE, BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE, BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZEby setting environment variables (-e ...lines in thedocker run ...command) which will override values set in makefiles. e.g
-e "BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE=94371840" \
- this will pick up the vendor blobs from
TheMuppetsbecause the default value forINCLUDE_PROPRIETARYistrue
docker run \
-e "BRANCH_NAME=v5.8" \
-e "DEVICE_LIST=pdx215" \
-v "/home/user/iode:/srv/src" \
-v "/home/user/zips:/srv/zips" \
-v "/home/user/logs:/srv/logs" \
-v "/home/user/cache:/srv/ccache" \
lineageos4microg/docker-lineage-cicd:pf-build-iodeOS- local manifest pointing to
- device and kernel sources, as they are not in the
LineageOSrepositories - proprietary vendor blobs, as they are not in the
TheMuppetsrepositories - this example picks up everything needed to build the Sony Xperia devices based on the
Yoshinoplatform (XZ1poplar&poplar_dsds, XZ1 Compactlilac, XZ Premiummaple&maple_dsds), from the repos used to make unofficial LineageOS builds for these devices. At the time of writing (January 2025) Android 14 /lineage-21.0is the latest branch available in those repos
- device and kernel sources, as they are not in the
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<!-- kernel -->
<project name="whatawurst/android_kernel_sony_msm8998" path="kernel/sony/msm8998" remote="github" revision="lineage-21" />
<!-- device trees -->
<project name="whatawurst/android_device_sony_yoshino-common" path="device/sony/yoshino-common" remote="github" revision="lineage-21" />
<project name="whatawurst/android_device_sony_maple" path="device/sony/maple" remote="github" revision="lineage-21" />
<project name="whatawurst/android_device_sony_maple_dsds" path="device/sony/maple_dsds" remote="github" revision="lineage-21" />
<project name="whatawurst/android_device_sony_poplar" path="device/sony/poplar" remote="github" revision="lineage-21" />
<project name="whatawurst/android_device_sony_poplar_dsds" path="device/sony/poplar_dsds" remote="github" revision="lineage-21" />
<project name="whatawurst/android_device_sony_lilac" path="device/sony/lilac" remote="github" revision="lineage-21" />
<!-- binary blobs -->
<project name="whatawurst/android_vendor_sony_maple" path="vendor/sony/maple" remote="github" revision="lineage-21" />
<project name="whatawurst/android_vendor_sony_maple_dsds" path="vendor/sony/maple_dsds" remote="github" revision="lineage-21" />
<project name="whatawurst/android_vendor_sony_poplar" path="vendor/sony/poplar" remote="github" revision="lineage-21" />
<project name="whatawurst/android_vendor_sony_poplar_dsds" path="vendor/sony/poplar_dsds" remote="github" revision="lineage-21" />
<project name="whatawurst/android_vendor_sony_lilac" path="vendor/sony/lilac" remote="github" revision="lineage-21" />
<project name="whatawurst/android_vendor_sony_yoshino-common" path="vendor/sony/yoshino-common" remote="github" revision="lineage-21" />
</manifest>- use
WITH_GMS=trueand the local manifest pointing to theandroid_vendor_partner_gmsrepository -
INCLUDE_PROPRIETARY=false- get the vendor blobs from the repos specified in the manifest - build for all variants of the devices, single-SIM and dual-SIM
docker run \
-e "BRANCH_NAME=lineage-21.0" \
-e "DEVICE_LIST=lilac,poplar,poplar_dsds,maple,maple_dsds" \
-e "WITH_GMS=true" \
-e "INCLUDE_PROPRIETARY=true" \
-v "/home/user/lineage:/srv/src" \
-v "/home/user/zips:/srv/zips" \
-v "/home/user/logs:/srv/logs" \
-v "/home/user/cache:/srv/ccache" \
lineageos4microg/docker-lineage-cicd- same local manifest for device and kernel sources and proprietary vendor blobs
- as for official devices (
WITH_GMS=false, no local manifest pointing to theandroid_vendor_partner_gmsrepository) -
INCLUDE_PROPRIETARY=false- get the vendor blobs from the repos specified in the manifest
docker run \
-e "BRANCH_NAME=lineage-21.0" \
-e "DEVICE_LIST=lilac,poplar,poplar_dsds,maple,maple_dsds" \
-e "WITH_GMS=false" \
-e "INCLUDE_PROPRIETARY=false" \
-v "/home/user/lineage:/srv/src" \
-v "/home/user/zips:/srv/zips" \
-v "/home/user/logs:/srv/logs" \
-v "/home/user/cache:/srv/ccache" \
lineageos4microg/docker-lineage-cicd- same local manifest for device and kernel sources and proprietary vendor blobs
- as for official devices (
WITH_GMS=false, no local manifest pointing to theandroid_vendor_partner_gmsrepository, IodéOS branch names, use the:pf-build-iodeOStag) -
INCLUDE_PROPRIETARY=false- get the vendor blobs from the repos specified in the manifest
docker run \
-e "BRANCH_NAME=lineage-21.0" \
-e "DEVICE_LIST=lilac,poplar,poplar_dsds,maple,maple_dsds" \
-e "WITH_GMS=false" \
-e "INCLUDE_PROPRIETARY=false" \
-v "/home/user/lineage:/srv/src" \
-v "/home/user/zips:/srv/zips" \
-v "/home/user/logs:/srv/logs" \
-v "/home/user/cache:/srv/ccache" \
lineageos4microg/docker-lineage-cicd:pf-build-iodeOSSee also `Build errors, fixes and work arounds' in my personal project wiki
- The following builds will fail if
WITH_GMS=trueis not set because their partition scheme will not have enough space to account for the iodé additions:-
bonito- Google Pixel 3a XL -
crosshatch- Google Pixel 3 XL -
sargo- Google Pixel 3a -
sunfish- Google Pixel 4a
-
To be written