| Both sides previous revision Previous revision Next revision | Previous revision Next revisionBoth sides next revision |
| docs:guide-user:additional-software:opkg [2021/03/26 11:20] – [Examples] links to mans vgaetera | docs:guide-user:additional-software:opkg [2023/04/03 00:34] – [Local repository] update vgaetera |
|---|
| |
| The ''opkg'' utility is the lightweight package manager used for this job. | The ''opkg'' utility is the lightweight package manager used for this job. |
| Opkg is a fork of ''ipkg'', the package manager used in NSLU2's [[http://www.nslu2-linux.org/wiki/Optware/|Optware]], which is designed to add software to stock firmware of embedded devices. | Opkg is a fork of ''ipkg'', the package manager used in NSLU2's [[https://web.archive.org/web/20200919214711if_/http://www2.nslu2-linux.org/wiki/pmwiki.php?pagename=Optware/HomePage|Optware]]<sup>(archive link)</sup>, which is designed to add software to stock firmware of embedded devices. |
| |
| Opkg is a full package manager for the root file system, including kernel modules and drivers, while ipkg is just a way to add software to a separate directory (e.g. ''/opt''). | Opkg is a full package manager for the root file system, including kernel modules and drivers, while ipkg is just a way to add software to a separate directory (e.g. ''/opt''). |
| |
| Opkg is sometimes called //Entware//, as it is used also in the [[http://entware.wl500g.info|Entware repository]] for embedded devices (a fork of OpenWrt community packages repository). | Opkg is sometimes called //Entware//, as it is also the package manager used by the [[https://github.com/Entware/Entware/wiki|Entware repository]] for embedded devices (itself a fork of OpenWrt's community packages repository). |
| |
| The package manager ''opkg'' attempts to resolve dependencies with packages in the repositories - if this fails, it will report an error and abort the installation of that package. | The package manager ''opkg'' attempts to resolve dependencies with packages in the repositories - if this fails, it will report an error and abort the installation of that package. |
| | ''**update**'' | Update list of available packages\\ This simply retrieves a file like this one: [[https://downloads.lede-project.org/snapshots/packages/aarch64_armv8-a/base/Packages|example]], for your installation and stores it on your [[wp>tmpfs|RAM partition]] under ''/tmp/opkg-lists''. As of LEDE 17.01, after the opkg upgrade, this folder occupies about 450 KiB of space. OPKG needs the content of this folder in order to install or upgrade packages or to print info about them. You can safely delete the contents of this folder anytime to free up some RAM (its content is also lost on reboot), don't forget to run ''opkg update'' again before you install a new package. | | | ''**update**'' | Update list of available packages\\ This simply retrieves a file like this one: [[https://downloads.lede-project.org/snapshots/packages/aarch64_armv8-a/base/Packages|example]], for your installation and stores it on your [[wp>tmpfs|RAM partition]] under ''/tmp/opkg-lists''. As of LEDE 17.01, after the opkg upgrade, this folder occupies about 450 KiB of space. OPKG needs the content of this folder in order to install or upgrade packages or to print info about them. You can safely delete the contents of this folder anytime to free up some RAM (its content is also lost on reboot), don't forget to run ''opkg update'' again before you install a new package. | |
| | ''**upgrade** <pkgs>'' | Upgrade packages\\ To upgrade a group of packages, run ''opkg upgrade //packagename1// //packagename2//''.\\ A list of upgradeable packages can be obtained with the ''opkg list-upgradable'' command.\\ ------------\\ :!: Since OpenWrt firmware stores the base system in a compressed read-only partition, any update to base system packages will be written in the read-write partition and therefore use more space than it would if it was just overwriting the older version in the compressed base system partition. It's recommended to check the available space in internal flash memory and the space requirements for updates of base system packages.\\ Upgrading packages you installed should not have this issue as they are already in the read-write partition so the new one will overwrite the older one, although checking before upgrading never hurts.\\ As a general rule of thumb, devices that have 8 MiB or more total flash size and no user-installed packages should not have space issues when updating base packages, and of course devices set up for [[docs:guide-user:additional-software:extroot_configuration|Extroot]] won't have any space issue.\\ To check for free space, write ''df -h /'' from SSH or go in Software page in Luci webinterface (System submenu --> Software) to see how much space is left in the internal storage.\\ Check the size of packages you want to update by writing ''opkg info package-name'' in SSH or by checking the package size listed in the table in Software page, or you can check the [[packages:start|Table of Packages]] here in the wiki. While the "size" in opkg is the size of package in a compressed archive, the jffs2 or ubifs read-write partition will use the same compression algorithm on the installed files, so it should have similar size when installed.\\ :!: The package repositories in the development snapshots are updated by the build bots to new versions very often, so it's very likely you won't be able to upgrade some packages due to broken dependencies with kernel or kernel-related packages. In that case, it's recommended to use the [[docs:guide-user:additional-software:imagebuilder|Image Builder]] and make a new firmware image with all packages you need and flash that instead of upgrading through opkg. | | | ''**upgrade** <pkgs>'' | Upgrade packages\\ To upgrade a group of packages, run ''opkg upgrade //packagename1// //packagename2//''.\\ A list of upgradeable packages can be obtained with the ''opkg list-upgradable'' command.\\ ------------\\ :!: Since OpenWrt firmware stores the base system in a compressed read-only partition, any update to base system packages will be written in the read-write partition and therefore use more space than it would if it was just overwriting the older version in the compressed base system partition. It's recommended to check the available space in internal flash memory and the space requirements for updates of base system packages.\\ Upgrading packages you installed should not have this issue as they are already in the read-write partition so the new one will overwrite the older one, although checking before upgrading never hurts.\\ As a general rule of thumb, devices that have 8 MiB or more total flash size and no user-installed packages should not have space issues when updating base packages, and of course devices set up for [[docs:guide-user:additional-software:extroot_configuration|Extroot]] won't have any space issue.\\ To check for free space, write ''df -h /'' from SSH or go in Software page in Luci webinterface (System submenu --> Software) to see how much space is left in the internal storage.\\ Check the size of packages you want to update by writing ''opkg info package-name'' in SSH or by checking the package size listed in the table in Software page, or you can check the [[packages:start|Table of Packages]] here in the wiki. While the "size" in opkg is the size of package in a compressed archive, the jffs2 or ubifs read-write partition will use the same compression algorithm on the installed files, so it should have similar size when installed.\\ :!: The package repositories in the development snapshots are updated by the build bots to new versions very often, so it's very likely you won't be able to upgrade some packages due to broken dependencies with kernel or kernel-related packages. In that case, it's recommended to use the [[docs:guide-user:additional-software:imagebuilder|Image Builder]] and make a new firmware image with all packages you need and flash that instead of upgrading through opkg. | |
| | ''**install** <pkgs|FQDN>'' | Install package(s)\\ Examples: <code bash>opkg install hiawatha | | ''**install** <pkgs|url>'' | Install package(s)\\ Examples: <code bash>opkg install hiawatha |
| opkg install http://downloads.openwrt.org/snapshots/trunk/ar71xx/packages/hiawatha_7.7-2_ar71xx.ipk | opkg install http://downloads.openwrt.org/snapshots/trunk/ar71xx/packages/hiawatha_7.7-2_ar71xx.ipk |
| opkg install /tmp/hiawatha_7.7-2_ar71xx.ipk</code> | | opkg install /tmp/hiawatha_7.7-2_ar71xx.ipk</code> | |
| |
| ===== Examples ===== | ===== Examples ===== |
| | ==== Basics ==== |
| <code bash> | <code bash> |
| # Install a package | # Install a package |
| </code> | </code> |
| |
| | ==== Extras ==== |
| You can make use of [[wp>Glob_(programming)|glob patterns]] directly and also write a little [[wp>Shell script|shell script]] to use [[wp>Regular expression|regular expressions]] and otherwise further process information. | You can make use of [[wp>Glob_(programming)|glob patterns]] directly and also write a little [[wp>Shell script|shell script]] to use [[wp>Regular expression|regular expressions]] and otherwise further process information. |
| Use a [[wp>Pipeline_(Unix)|pipeline]] and [[man>grep(1)|grep]], or [[man>awk(1)|awk]], or [[man>sed(1)|sed]] to filter that output: | Use a [[wp>Pipeline_(Unix)|pipeline]] and [[man>grep(1)|grep]], or [[man>awk(1)|awk]], or [[man>sed(1)|sed]] to filter that output: |
| opkg list | grep -e <pattern1> -e <pattern2> | opkg list | grep -e <pattern1> -e <pattern2> |
| opkg list | awk -e '/<pattern>/{print $0}' | opkg list | awk -e '/<pattern>/{print $0}' |
| opkg info kmod-ipt-* | awk -e '/length/{print $0}' | opkg info kmod-nf-\* | awk -e '/length/{print $0}' |
| opkg list-installed | awk -e '{print $1}' | tr '\n' ' ' | opkg list-installed | awk -e '{print $1}' | tr '\n' ' ' |
| for pkg in <package1> <package2> <package3>; do opkg info ${pkg}; done | for pkg in <package1> <package2> <package3>; do opkg info ${pkg}; done |
| </code> | </code> |
| |
| :!: Mass upgrade of all packages is [[meta:infobox:upgrade_packages_warning|strongly discouraged]]. | ==== Upgrading packages ==== |
| If you still want to proceed, set up [[docs:guide-user:advanced:opkg_extras|Opkg extras]] or use the following one-liner: | <WRAP important> |
| | Mass upgrade of all packages is [[meta:infobox:upgrade_packages_warning|strongly discouraged]]. |
| | The chance of soft-bricking your device is significant, so be fully prepared to perform a [[docs:guide-user:troubleshooting:failsafe_and_factory_reset|recovery and factory reset in failsafe mode]]. |
| | Proceed at your own risk. |
| | </WRAP> |
| |
| <code bash> | <code bash> |
| |
| ==== Proxy support ==== | ==== Proxy support ==== |
| | OpenWrt 21.02: |
| | |
| | <code bash> |
| | # Configure profile |
| | mkdir -p /etc/profile.d |
| | cat << "EOF" > /etc/profile.d/custom.sh |
| | export https_proxy=http://proxy.example.org:8080/ |
| | EOF |
| | . /etc/profile |
| | |
| | # Workaround |
| | sed -i -e "s/https/http/" /etc/opkg/distfeeds.conf |
| | </code> |
| | |
| To use ''opkg'' through a proxy, add the following to ''/etc/opkg.conf'': | To use ''opkg'' through a proxy, add the following to ''/etc/opkg.conf'': |
| |
| |
| ===== Troubleshooting ===== | ===== Troubleshooting ===== |
| ==== Out of space ==== | ==== Verbose opkg update ==== |
| If //opkg// runs out of space, it usually fails to recover cleanly leaving dangling lock files in place resulting in a ''//Could not obtain administrative lock//'' error. | <code bash> |
| The lock file can be deleted by issuing the ''rm /usr/lib/opkg/lock'' command. | # Save the script |
| | cat << "EOF" > opkg-update.sh |
| | #!/bin/sh |
| | rm -f -R /tmp/opkg-lists |
| | mkdir -p /tmp/opkg-lists |
| | while read TYPE REPO URL |
| | do |
| | wget -O /tmp/opkg-lists/"${REPO}".gz "${URL}"/Packages.gz |
| | wget -O /tmp/opkg-lists/"${REPO}".sig "${URL}"/Packages.sig |
| | gunzip -k /tmp/opkg-lists/"${REPO}".gz |
| | usign -V -P /etc/opkg/keys -m /tmp/opkg-lists/"${REPO}" 2>&1 \ |
| | | grep -e "^OK$" \ |
| | && mv -f /tmp/opkg-lists/"${REPO}".gz /tmp/opkg-lists/"${REPO}" |
| | done < /etc/opkg/distfeeds.conf |
| | EOF |
| | chmod +x opkg-update.sh |
| |
| Additionally, //opkg// may not remove the files it was installing. | # Run the script |
| | ./opkg-update.sh |
| One way to do this is get a list of the files it was installing, then delete them. | |
| | |
| Replace the url with the appropriate package. | |
| | |
| <code bash> | |
| (cd /; \ | |
| wget -q -O - http://download.link.to.package \ | |
| | tar -Oxz ./data.tar.gz | tar -tz | xargs rm) | |
| </code> | </code> |
| |
| However, the above line does not delete the dependencies that were installed along with the package responsible. | ==== Out of space ==== |
| Also, it leaves empty directories around. | Remove partly installed packages and their dependencies if //opkg// runs out of space during a transaction. |
| The script below intends to fix those. | |
| |
| <code bash> | <code bash> |
| # Save the script | # Save the script |
| cat << "EOF" > opkgremovepartlyinstalledpackage.sh | cat << "EOF" > opkg-rm-pkg-deps.sh |
| #!/bin/sh | #!/bin/sh |
| # takes one argument/parameter: the name of the package which didn't install | |
| # correctly and should be removed along with its dependencies | |
| # example: ./opkgremovepartlyinstalledpackage.sh pulseaudio-daemon | |
| |
| # get list of all packages that would be installed along with package x | |
| PKGS="$(opkg --force-space --noaction install ${1} \ | |
| | grep -e "http:" \ | |
| | cut -f 2 -d " " \ | |
| | sed -e "s/\.$//")" | |
| opkg update | opkg update |
| | URL="$(opkg --force-space --noaction install "${@}" \ |
| for PKG in ${PKGS} | | sed -n -e "/^Downloading\s*/s///p")" |
| do | rm -f /usr/lib/opkg/lock |
| LIST="$(wget -q -O - "${PKG}" | for URL in ${URL} |
| | tar -Oxz ./data.tar.gz \ | do FILE="$(wget -q -O - "${URL}" \ |
| | tar -t -z \ | | tar -O -x -z ./data.tar.gz \ |
| | sort -r \ | | tar -t -z \ |
| | sed -e "s/^./\/overlay\/upper/")" | | sort -r \ |
| for FILE in ${LIST} | | sed -e "s|^\.|/overlay/upper|")" |
| do | for FILE in ${FILE} |
| if [ -f "${FILE}" ] | do if [ -f "${FILE}" ] |
| then | then rm -f "${FILE}" |
| echo "Removing file ${FILE}" | elif [ -d "${FILE}" ] |
| rm -f "${FILE}" | then rmdir "${FILE}" |
| elif [ -d "${FILE}" ] | fi |
| then | done |
| echo "Removing directory ${FILE} if empty" | |
| rmdir -f "${FILE}" | |
| fi | |
| done | |
| done | done |
| echo "You may need to reboot for the free space to become visible" | |
| EOF | EOF |
| chmod +x ./opkgremovepartlyinstalledpackage.sh | chmod +x opkg-rm-pkg-deps.sh |
| | </code> |
| | |
| | <code bash> |
| |
| # Run the script | # Run the script |
| ./opkgremovepartlyinstalledpackage.sh <package-name> | ./opkg-rm-pkg-deps.sh package_name |
| | |
| | # Reboot to make the free space visible |
| | reboot |
| </code> | </code> |
| |
| ==== Local repository ==== | ==== Local repository ==== |
| FIXME Convert this into LEDE and explain what it is actually doing. | There may be use cases where having a package repository on the device itself is advantageous: |
| | * Unreliable WANs, where the connectivity upstream of the device to a remote repository goes down for an unacceptable period of time. |
| | * Bandwidth Caps, where the connectivity upstream of the device to a remote repository has a limited amount of data that can be fetched before the connectivity is throttled or goes down until the next period where the cap resets. |
| | * A repository with customization; built from source, which isn't available from remote repositories. |
| | * The device acts as a reference device for other systems, to ensure that the package versions across the devices local to the network remain consistent. |
| |
| Live example: | Set up a local repository for your target. |
| | Assuming about 2-3 GB of free space is available. |
| |
| <code bash> | <code bash> |
| r=44685 | # Install packages |
| search="http://downloads.openwrt.org/snapshots/trunk/ar71xx/generic" | opkg update |
| replace="file:///mnt/sdcard/shared/users/www/r$r" | opkg install rsync |
| sed -i -e "s!$search!$replace!" /etc/opkg.conf | |
| </code> | |
| |
| Share for a second router: | # Save the script |
| | cat << "EOF" > opkg-sync-local-repo.sh |
| | #!/bin/sh |
| | . /etc/os-release |
| | REPO_LOCAL="file://${1:-/${ID}}/" |
| | REPO_URL="https://downloads.${HOME_URL#*//}" |
| | case "${VERSION_ID}" in |
| | (snapshot) REPO_DIR="downloads/snapshots" ;; |
| | (*) REPO_DIR="downloads/releases/${VERSION_ID}" ;; |
| | esac |
| | REPO_CORE="${REPO_DIR}/targets/${OPENWRT_BOARD}" |
| | REPO_PKGS="${REPO_DIR}/packages/${OPENWRT_ARCH}" |
| | for REPO_DIR in "${REPO_CORE}" "${REPO_PKGS}" |
| | do mkdir -p "${REPO_LOCAL#*//}${REPO_DIR#*/}" |
| | rsync --bwlimit="8M" --del -r -t -v \ |
| | "${REPO_URL/https/rsync}${REPO_DIR}/" \ |
| | "${REPO_LOCAL#*//}/${REPO_DIR#*/}/" |
| | done |
| | EOF |
| | chmod +x opkg-sync-local-repo.sh |
| |
| <code bash> | # Run the script |
| ln -s /mnt/sdcard/shared/users/www /www/pendrive | ./opkg-sync-local-repo.sh /openwrt |
| </code> | |
| |
| In the second router: | # Configure Opkg to use local repo |
| | . /etc/os-release |
| | REPO_LOCAL="file:///${ID}/" |
| | REPO_URL="https://downloads.${HOME_URL#*//}" |
| | sed -i -e "s|${REPO_URL}|${REPO_LOCAL}|" /etc/opkg/distfeeds.conf |
| |
| <code bash> | # Share the repository on the LAN |
| r=44685 | ln -f -s ${REPO_LOCAL#*//} /www/${ID} |
| search="downloads.openwrt.org/snapshots/trunk/ar71xx/generic" | |
| replace="192.168.1.1/pendrive/r$r" | # Configure Opkg on the clients |
| sed -i -e "s!$search!$replace!" /etc/opkg.conf | . /etc/os-release |
| | REPO_LOCAL="http://192.168.1.1/${ID}/" |
| | REPO_URL="https://downloads.${HOME_URL#*//}" |
| | sed -i -e "s|${REPO_URL}|${REPO_LOCAL}|" /etc/opkg/distfeeds.conf |
| </code> | </code> |
| | |
| | See also: [[:downloads#how_to_mirror|How to mirror]] |
| |
| ===== Non-standard installation destinations ===== | ===== Non-standard installation destinations ===== |
| </WRAP> | </WRAP> |
| |
| The default opkg.conf actually contains three destinations: | The default ''/etc/opkg.conf'' actually contains three destinations: |
| |
| <code bash> | <code bash> |