Offline Firmware¶
The LVFS is a public webservice designed to allow OEMs and ODMs to upload firmware easily, and for it to be distributed securely to tens of millions of end users. For some people, this simply does not work for various reasons:
They don’t trust the LVFS team, fwupd.org, GPG, certain OEMs or the CDN we use
They don’t want thousands of computers on an internal network downloading all the files over and over again
The internal secure network has no internet connectivity
For these cases there are a few different ways to keep your hardware updated, in order of simplicity:
Deploy in immutable image¶
If the OS is shipped as an image, you can just install the .cab
files into
/usr/share/fwupd/remotes.d/vendor/firmware
and then enable vendor-directory.conf
with fwupdmgr enable-remote vendor-directory
.
Then once you have disabled the public LVFS using fwupdmgr disable-remote lvfs
,
running fwupdmgr
will use only the cabinet archives you deploy in your
immutable image.
Of course, you’re deploying a larger image because you might have several unused
firmware files included for each image, but this is how Google Chrome OS is using
fwupd.
Mirror the public firmware¶
To mirror the entire archive (over 10,000 files) you must use authentication when cloning as there is a global unauthenticated limit of 1,000 downloads per-IP per-day. Basic authentication should be used, with your email address used on the LVFS as the username and the generated user token as the password.
If you do not have an LVFS login, please open an issue to request a free user account.
Using pulp-server¶
You can use Pulp to mirror the entire public contents of the LVFS (but never private or embargoed firmware). Create a repo pointing to PULP_MANIFEST and then sync that on a regular basis to download the metadata and firmware. The contents will not change any more frequently than every 4 hours, so please use a polling interval of at least that.
Using a helper script¶
There is a helper script sync-pulp.py
that can be used if pulp-server
is not installed:
./contrib/sync-pulp.py https://fwupd.org/downloads /mnt/mirror \
--username=login@name.com \
--token=XA1A5ZV7R65FUZBZ
You can then use a webserver such as Nginx or Apache to export /mnt/mirror
as https://my.private.server/mirror
.
Then, disable the LVFS by deleting or modifying /etc/fwupd/remotes.d/lvfs.conf
and then create a /etc/fwupd/remotes.d/myprivateserver.conf
file:
[fwupd Remote]
Enabled=true
Type=download
MetadataURI=https://my.private.server/mirror/firmware.xml.gz
FirmwareBaseURI=https://my.private.server/mirror
To instead mirror the private embargoed files, you can use:
./contrib/sync-pulp.py https://fwupd.org/downloads /mnt/mirror \
--embargo \
--username=login@name.com \
--token=XA1A5ZV7R65FUZBZ
Warning
Do not use your login password here! Generate a token when logged in to the LVFS using the User Profile settings.
To restrict the downloaded firmware to a specific tag (perhaps a vendor Best Known Configuration) use the following command:
./contrib/sync-pulp.py https://fwupd.org/downloads /mnt/mirror \
--filter-tag=hughski-2020q1 \
--username=login@name.com \
--token=XA1A5ZV7R65FUZBZ
Note, this command can be run safely multiple times with different --filter-tag
values on the
same destination directory; the superset of files will be downloaded.
Approved firmware¶
By exporting the entire LVFS (including the metadata, and metadata signature) you can still delay the deployment of firmware. Using the approved firmware list the client can filter out firmware that has not been tested by your organization without creating and signing a custom remote.
The allow-list of firmware can be set using:
fwupdmgr set-approved-firmware checksum1,checksum2,checksum3
Some versions of fwupd (>= 1.7.1) also support loading the list of checksums using a filename, e.g.
fwupdmgr set-approved-firmware filename
…where checksum
is the SHA1 or SHA256 checksum of the .cab
archive.
Note
The org.freedesktop.fwupd.set-approved-firmware
PolicyKit action
may require root permission to use.
Downloading manually¶
Download the .cab
files that match your hardware and then install them
on the target hardware via Ansible or
Puppet using fwupdmgr install foo.cab
. You can also
use fwupdagent get-devices
to get the existing firmware versions of all
hardware in a format you can parse from scripts.
Building a custom remote¶
The local.py
script allows you to create the metadata for a directory of .cab
files.
Note
If you want to use signed metadata then please use
jcat-tool firmware.xml.gz.jcat firmware.xml.gz CERTIFICATE PRIVATE_KEY
.
You will need to create a custom certificate
and you’ll also need to distribute the the PKCS#7 certificate on all clients
that are going to use the remote.
Create your own LVFS¶
The LVFS is a free software Python 3 Flask application and an instance can be set up internally if required. You have to configure much more this way, including generating your own GPG and PKCS#7 keys, uploading your own firmware and setting up users and groups on the server.
Doing all this has a few advantages, namely:
You can upload each firmware file and QA it, only pushing it to stable when ready
You don’t ship firmware which you didn’t upload
You can control the staged deployment, e.g. only allowing the same update to be deployed to 1000 servers per day
You can see failure reports from clients, to verify if the deployment is going well
You can see nice graphs about how many updates are being deployed across your organization
However, running a secure LVFS instance is a lot of work as PostgreSQL has to be used as a database, Redis has to also be set up as a queue manager, and Celery is used to manage the worker queues.
Although minor versions of the LVFS can be upgraded easily, you should review all the commits to lvfs-website to ensure that any manual migration is also performed.