This repository contains scripts to create Docker containers hosting OpenWrt. https://hub.docker.com/r/openwrtorg/rootfs
 
Go to file
Josef Schlehofer 979b1393ae
ci: limit GITHUB_TOKEN permissions
The workflow does not set any permissions, so every job gets the
repository default, which grants write access to everything. Drop all
permissions by default and grant each job only what it needs: reading the
repository, and writing packages to push to ghcr.io.

Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
2026-09-14 23:37:37 +02:00
.github ci: limit GITHUB_TOKEN permissions 2026-09-14 23:37:37 +02:00
keys keys: add new Nitrokey based key 2024-11-06 15:35:20 +01:00
.gitignore expand gitignore with usign/ & gpg/ 2019-10-11 13:56:14 -10:00
Dockerfile Dockerfile: fix GPG keys permission issues during container setup 2025-04-03 19:21:04 +00:00
Dockerfile.rootfs Dockerfile.rootfs: drop dangling /etc/resolv.conf symlink 2026-08-17 09:41:15 +02:00
LICENSE Add a copy of the license 2019-07-10 12:12:27 +02:00
README.md ci: push images to the owner's namespace, not the login user 2026-09-14 23:37:36 +02:00
setup.sh ci: fix DOWNLOAD_FILE expansion for rootfs builds 2026-08-17 09:34:39 +02:00

README.md

OpenWrt Docker repository

GPL-2.0-only License CI Docker Hub

This repository contains files to create OpenWrt containers. While mostly used for our CI you may use the scripts to build containers on your own.

[!WARNING] Starting with the branch of OpenWrt 24.10 any snapshot (aka nightly), builds no longer contain the actual binaries, but instead a setup.sh script. The environment variables are set automatically per container to download the correct archive containing the SDK/ImageBuilder/rootfs. This dramatically reduces bandwidth and storage usage. Sorry for the inconvenience.

Available containers:

  • sdk compile OpenWrt packages
  • imagebuilder create firmware images
  • rootfs test software inside an OpenWrt runtime

All containers are mirrored to the following three registries under openwrt account:

* We have switched our account from openwrtorg to openwrt on docker.io

Find more details on the container types below

sdk

Contains the OpenWrt SDK based on the same container we use for our Buildbot infrastructure. This can be useful when building packages on macOS, Windows or via CI.

SDK Example

docker run --rm -v "$(pwd)"/bin/:/builder/bin -it openwrt/sdk
# inside the Docker container
[ ! -d ./scripts ] && ./setup.sh
./scripts/feeds update packages
make defconfig
./scripts/feeds install tmate
make package/tmate/{clean,compile} -j$(nproc)

Enjoy a local OpenWrt SDK container building the tmate package with the binary in hosts ./bin folder.

SDK Tags

All currently available SDKs via tags in the following format:

  • <target>-<subtarget>[-<branch|tag|version>]
  • <arch>[-<branch|tag|version>]

The branch|tag|version can be something like openwrt-22.03 (branch), v22.03.4 (tag) or 21.02.3 (version). To use daily builds use either main or SNAPSHOT.

imagebuilder

Contains the OpenWrt ImageBuilder based on the same container we use for our buildbot infrastructure. This can be useful when creating images on macOS, Windows or via CI.

ImageBuilder Example

Built images will be stored in bin, and cached packages, that can be reused for other builds - in dl. Packages from differenet platforms/versions might have the same package names, but different checksums, which will cause errors during build, so working directories shouldn't be shared between different image builders.

If you're running on a SELinux-enabled system (e.g. RHEL), volumes must be mounted with a :z flag:

--volume "$(pwd)"/bin/:/builder/bin:z

Using Docker:

# NB: Replace these variables, according to your needs
PLATFORM=ath79-generic
VERSION=25.12.5
PROFILE=tplink_archer-c7-v2
PACKAGES="ath10k-firmware-qca988x kmod-ath10k kmod-usb-ledtrig-usbport kmod-usb-net-cdc-ether kmod-usb2 luci luci-ssl luci-app-sqm luci-app-attendedsysupgrade owut -ppp -ppp-mod-pppoe -luci-proto-ppp -ath10k-firmware-qca988x-ct -kmod-ath10k-ct"

mkdir -p openwrt-${PLATFORM}-${VERSION}/{bin,dl}
cd openwrt-${PLATFORM}-${VERSION}

docker run --rm \
  --volume "$(pwd)"/bin/:/builder/bin \
  --volume "$(pwd)"/dl:/builder/dl \
  openwrt/imagebuilder:${PLATFORM}-${VERSION} \
  sh -c "
    [ ! -d ./scripts ] && ./setup.sh;
    make image PROFILE='${PROFILE}' PACKAGES='${PACKAGES}'
  "

Using Podman we need to map user account to same UID within container using --userns=keep-id:

# Same variables as above

podman run --rm \
  --userns=keep-id \
  --volume "$(pwd)"/bin/:/builder/bin \
  --volume "$(pwd)"/dl:/builder/dl \
  openwrt/imagebuilder:${PLATFORM}-${VERSION} \
  sh -c "
    [ ! -d ./scripts ] && ./setup.sh;
    make image PROFILE='${PROFILE}' PACKAGES='${PACKAGES}'
  "

Variables can be inlined to make these into one-liners.

For snapshots use VERSION=SNAPSHOT.

ImageBuilder Tags

All currently available ImageBuilders via tags in the following format:

  • <target>-<subtarget>[-<branch|tag|version>]
  • <arch>[-<branch|tag|version>]

The branch|tag|version can be something like openwrt-22.03 (branch), v22.03.4 (tag) or 21.02.3 (version). To use daily builds use either main or SNAPSHOT.

rootfs (experimental)

The OpenWrt runtime uses multiple active services to work, it's not really suited as a container. This rootfs should only be used for special cases like CI testing.

An unpackaged version of OpenWrt's rootfs for different architectures. The ./rootfs folder requires slight modifications to work within Docker, additional files for the rootfs should be added there before building.

Rootfs Example

docker run --rm -it openwrt/rootfs
# inside the Docker container
[ ! -d ./scripts ] && ./setup.sh
mkdir /var/lock/
opkg update
opkg install tmate
tmate

Enjoy a local OpenWrt container running the x86/64 architecture with internet access. Once closed the container is removed.

Rootfs Tags

|||armvirt/32|armvirt/64|malta/be|mvebu/cortexa9

  • x86/64 or x86_64
  • x86/generic or i386_pentium4
  • x86/geode or i386_pentium-mmx
  • armvirt/32 or arm_cortex-a15_neon-vfpv4
  • armvirt/64 or aarch64_cortex-a53
  • malta/be or mips_24kc
  • mvebu/cortexa9 or arm_cortex-a9_vfpv3-d16

GitHub Actions CI & Registries

The GitHub Actions workflow .github/workflows/containers.yml builds the containers and pushes them to <registry>/<repository owner>/<image>, so forks push to their own namespace.

Pushing to ghcr.io works out of the box using GitHub's built-in GITHUB_TOKEN. To also push to Docker Hub or Quay.io, configure the following secrets under your repository's Settings -> Secrets and variables -> Actions. A registry without both its user and token is skipped.

  • DOCKER_USER and DOCKER_TOKEN - the Docker Hub user and its Personal Access Token.
  • QUAY_USER and QUAY_TOKEN - the Quay.io user or robot account (org+name) and its token. A robot account needs write permission on the existing sdk, imagebuilder and rootfs repositories.

To push to a different namespace than the repository owner, set the DOCKER_NAMESPACE or QUAY_NAMESPACE variable. The login user needs push access to it.

Build Your Own

If you wan to create your own container you can use the Dockerfile. You can set the following build arguments:

  • TARGET - the target to build for (e.g. x86/64)
  • DOWNLOAD_FILE - the file to download (e.g. imagebuilder-.*x86_64.tar.xz)
  • FILE_HOST - the host to download the ImageBuilder/SDK/rootfs from (e.g. downloads.openwrt.org)
  • VERSION_PATH - the path to the ImageBuilder/SDK/rootfs (e.g. snapshots or releases/21.02.3)

Example ImageBuilder

If you plan to use your own server please add your own GPG key to the ./keys/ folder.

docker build \
    --build-arg TARGET=x86/64 \
    --build-arg DOWNLOAD_FILE="imagebuilder-.*x86_64.tar.[xz|zst]" \
    --build-arg FILE_HOST=downloads.openwrt.org \
    --build-arg VERSION_PATH=snapshots \
    -t openwrt/x86_64 .