dnf local

Summary

Ross’s quick guide to “dnf local”.

I have multiple Fedora 28 installs at my house with only slight differences.

What I want is to be able to do one:

[root@fubar ~]# dnf upgrade
Last metadata expiration check: 0:02:37 ago on Wed 13 Mar 2019 10:51:07 AM CDT.
Dependencies resolved.
===============================================================================
 Package                 Arch        Version                Repository    Size
===============================================================================
Upgrading:
 btrfs-progs             x86_64      4.20.2-1.fc28          updates      784 k
...

And have other “upgrade” at my house use “a local dnf repo” if the “Package” was already downloaded like1:

[root@snafu ~]# dnf upgrade
Last metadata expiration check: 0:00:00 ago on Wed 13 Mar 2019 11:29:30 AM CDT.
Dependencies resolved.
===============================================================================
 Package                Arch     Version              Repository          Size
===============================================================================
Upgrading:
 btrfs-progs            x86_64   4.20.2-1.fc28        fubar-local-repo   784 k
...

TODOs

There are at least two “TODOs” I can think of on 13MAR2019WED:

  1. Being paranoid I want to make sure the local really has just what was last needed by the “server dnf upgrade” so I’m think a heavy handed “delete the old repo and recreate”.
  2. When I go from Fedora 28 to Fedora 29 I probably should turn this off.

Server Names/Functions

For purposes of this document here’s the names and function:

SERVER NAME FUNCTION
fubar main master server – dnf repo, ftp server, master for files, backups, webpages, etc
snafu laptop client – references above dnf repo if possible
etc other laptops and functions – references above dnf repo if possible

Notice we’re setting up a traditional “client/server” relationship with:

  • server -> fubar
  • client -> snafu

Master

These are the things you do on the master!

dnf plugin local

On the “main server” (and nowhere else) install “plugin local” like:

[root@fubar ~]# dnf install python3-dnf-plugin-local

It’s quite possible you just retry “dnf” and get something like:

[root@fubar ~]# dnf search bogus
Failed to synchronize cache for repo '_dnf_local', disabling.
...

Read on …

This will create a config like:

/etc/dnf/plugins/local.conf

And it’s referencing a directory that probably doesn’t exist and certainly doesn’t have a “dnf repository” available. So let’s modify the config thusly:

[main]
enabled = true
# Path to the local repository.
# repodir = /var/lib/dnf/plugins/local
# added by ross
repodir = /var/ftp/pub/dnfrepo
...

I use anonymous ftp to present repos like “CPAN” and “dnf” so I put it under “/var/ftp/pub/”. When I create the “dnfrepo” I “chmod 2775” to my user so I have “control over the files” (read that “can remove”) without using root (later we’ll do a “rm -rf” and I hate doing that as root). Something like (note I’m not sure for what I want which is “group file permission will be read/write” that “g::rwX” would change anything):

[root@fubar ~]# mkdir /var/ftp/pub/dnfrepo/
[root@fubar ~]# chown root:myuser /var/ftp/pub/dnfrepo/
[root@fubar ~]# chmod 2775 /var/ftp/pub/dnfrepo/
[root@fubar ~]# setfacl -d -m g::rwx /var/ftp/pub/dnfrepo/

Reset Repo

This is not done the first time!

The point of this is not to have a complete mirror repo. It’s more important that it be “correct” (current) and it’s valid after the run on the server. So before a “dnf upgrade” I clean out like (only the commands in red need to be run as root):

[ross@fubar ~]$ rm -f           /var/ftp/pub/dnfrepo/*.rpm
[ross@fubar ~]$ rm -rf          /var/ftp/pub/dnfrepo/repodata/
[root@fubar ~]# createrepo_c -v /var/ftp/pub/dnfrepo/

createrepo_c

If you read the comments carefully in the config above you’ll see it wants something called “createrepo_c” so I tried:

[root@fubar ~]# dnf install createrepo_c
Failed to synchronize cache for repo '_dnf_local', disabling.
Last metadata expiration check: 0:56:36 ago on Wed 13 Mar 2019 09:53:18 AM CDT.
Package createrepo_c-0.10.0-19.fc28.x86_64 is already installed, skipping.
Dependencies resolved.
Nothing to do.
Complete!

So despite what the comments in the config say it doesn’t initialize the new “repo directory” automatically so I did:

[root@fubar ~]# createrepo_c -v /var/ftp/pub/dnfrepo
...
10:50:44: All done

If I list my “repo” now there’s not much in it:

[root@fubar ~]# ls -a /var/ftp/pub/dnfrepo
. .. repodata

Now when you run “dnf” the next time it will find your repo like:

[root@fubar ~]# dnf search bogus
_dnf_local 251 kB/s | 257 B 00:00 
Last metadata expiration check: 0:00:00 ago on Wed 13 Mar 2019 10:51:07 AM CDT.
...

And the next time I do a “dnf upgrade” I see what I want:

[root@fubar ~]# dnf upgrade
Last metadata expiration check: 0:02:37 ago on Wed 13 Mar 2019 10:51:07 AM CDT.
...
btrfs-progs x86_64 4.20.2-1.fc28 updates 784 k
...
Total download size: 9.7 M
Is this ok [y/N]: y
Downloading Packages:
(1/16): libsmbclient-4.8.8-0.fc28_4.8.9-1.fc28 231 kB/s | 89 kB 00:00
...

So I did all of this to “save” downloading 9.7M … but I learned a lot 🙂 2

If I list my repo directory now I see:

[root@fubar ~]# ls -a /var/ftp/pub/dnfrepo/
.
..
btrfs-progs-4.20.2-1.fc28.x86_64.rpm
...
libsmbclient-4.8.9-1.fc28.x86_64.rpm
...
repodata
...

The “server” is now complete let’s move onto the “client” and get it to reference our “dnf repo service”.

Client

How to get the “client” to reference the new “dnf repo service”?

dnf repo

Immediately after the “server” above finish on the client when I run “dnf upgrade” notice I’m going to download the same packages … this is what I’m trying to prevent:

[root@snafu ~]# dnf upgrade
Last metadata expiration check: 0:00:46 ago on Wed 13 Mar 2019 11:05:58 AM CDT.
Dependencies resolved.
===============================================================================
Package Arch Version Repository Size
===============================================================================
Upgrading:
  btrfs-progs x86_64 4.20.2-1.fc28 updates 784 k
...

So let’s create a “repo file” that references out new “local just downloaded repo”. It will be at:

/etc/yum.repos.d/fubar-local.repo

And have contents:

[fubar-local-repo]
name=Fubar Local Repository
#baseurl=file:///testrepo/
baseurl=ftp://fubar/pub/dnfrepo/
enabled=1
gpgcheck=0
priority = 10
metadata_expire = 60

The “priority = 10” is very important. Without it “dnf” will see your repo has identical stuff to “upgrade” and ignore our new repo.

The “metadata_expire = 60” is important. Basically it says re-read this repo after 1 minute (60 seconds). You really don’t want to “dnf ‐‐refresh upgrade” all the time because just “refresh-ing” the repos takes “Fedora 28 – x86_64 => 30 MB (00:38 min:sec)” and “Fedora 28 – x86_64 1.2 => 60 MB 00:51 (min:sec)” respectively. That 90MB will quickly offset any gain this might provide. So by setting “metadata_expire = 60” you force “fubar-local-repo” basically everytime you use it like:

[root@snafu ~]# dnf upgrade
Fubar Local Repository                         243 kB/s |  11 kB     00:00 
...

Let’s update our “dnf repo” like:

[root@snafu ~]# dnf repolist
Fubar Local Repository                         404 kB/s |  19 kB     00:00    
Last metadata expiration check: 0:00:00 ago on Wed 13 Mar 2019 11:28:27 AM CDT.
repo id                    repo name                                     status
*fedora                    Fedora 28 - x86_64                            57,327
fedora-cisco-openh264      Fedora 28 openh264 (From Cisco) - x86_64           8
fubar-local-repo           Fubar Local Repository                            16
google-chrome              google-chrome                                      3
*rpmfusion-free            RPM Fusion for Fedora 28 - Free                  563
*rpmfusion-free-updates    RPM Fusion for Fedora 28 - Free - Updates        276
*updates                   Fedora 28 - x86_64 - Updates                  21,508

If  you check all your repos you should see:

[root@snafu ~]# dnf repolist all
Last metadata expiration check: 2:08:51 ago on Wed 13 Mar 2019 06:05:59 PM CDT.
repo id                                   repo name             status
...
fubar-local-repo                          Fubar Local Repositor enabled:     16
...
*updates                                  Fedora 28 - x86_64 -  enabled: 21,508
...

Use Our New Repo

Let’s do a normal “dnf upgrade” and check the output closely to see if our new repo is going to be used:

[root@snafu ~]# dnf upgrade
Last metadata expiration check: 0:00:00 ago on Wed 13 Mar 2019 11:29:30 AM CDT.
Dependencies resolved.
===============================================================================
 Package                Arch     Version              Repository          Size
===============================================================================
Upgrading:
 btrfs-progs            x86_64   4.20.2-1.fc28        fubar-local-repo   784 k
...
 google-chrome-stable   x86_64   73.0.3683.75-1       google-chrome       55 M
 libsmbclient           x86_64   2:4.8.9-1.fc28       fubar-local-repo   136 k
...

How cool is that? 🙂

dnf Commands

Most of the time the only “dnf” command I run is “upgrade” like:

[root@snafu ~]# dnf upgrade

‐‐disablerepo

I almost never set “auto yes” so I always have a chance to say “N” on an upgrade so it’s safe to use ‐‐disablerepo to see what the effects are like:

[root@snafu ~]# dnf upgrade
Last metadata expiration check: 0:00:00 ago on Thu 14 Mar 2019 08:05:20 PM CDT.
Dependencies resolved.
===============================================================================
 Package               Arch         Version                Repository     Size
===============================================================================
Upgrading:
...
 pcre                x86_64     8.43-1.fc28         fubar-local-repo     208 k

Transaction Summary
===============================================================================
Upgrade 6 Packages

Total download size: 93 M
Is this ok [y/N]: N
Operation aborted.

If I need to make sure my custom repo isn’t hurting anything I can disable for just the one command like:

[root@snafu ~]# dnf --disablerepo=fubar-local-repo upgrade
Last metadata expiration check: 0:11:32 ago on Thu 14 Mar 2019 07:51:29 PM CDT.
Dependencies resolved.
===============================================================================
 Package               Arch         Version                Repository     Size
===============================================================================
Upgrading:
...
 pcre                  x86_64       8.43-1.fc28            updates       208 k

Transaction Summary
===============================================================================
Upgrade 6 Packages

Total download size: 93 M
Is this ok [y/N]: N
Operation aborted.

setopt

Above I had you set “priority” in the config file using a text editor, that could have been:

[root@snafu ~]# dnf config-manager --setopt priority=11 --save fubar-local-repo
Main config did not have a priority attr. before setopt
Main config did not have a priority attr. before setoptnext

Those “did not have” messages bother me but if you check out the master log file it did not change:

[root@snafu ~]# cat /etc/dnf/dnf.conf
[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=True

And if you check the “repo file” for our repo “fubar-local-repo” you’ll see the “11” like:

[root@snafu ~]# cat /etc/yum.repos.d/fubar-local.repo
[fubar-local-repo]
name=Fubar Local Repository
#baseurl=file:///testrepo/
baseurl=ftp://fubar/pub/dnfrepo/
enabled=1
gpgcheck=0
priority = 11

The full list of “options” is easy to find like:

[root@snafu ~]# dnf config-manager --dump fubar-local-repo
=========================== repo: fubar-local-repo ============================
[fubar-local-repo]
...
priority = 11
...

Notice you see our “priority” we just set. Also notice some stuff from the master dnf conf is not present like “clean_requirements_on_remove” is not seen. If you want to see “master” leave off the repo like:

[root@snafu ~]# dnf config-manager --dump
==================================== main =====================================
[main]
...
clean_requirements_on_remove = True
...

And you do not see our “priority”.

I know of no built in way to see if an option is a default or from what config file. It’s not overly challenging to do some “grepp’ing” between files and have to do it so seldom I’ve never bothered to script it.

And finally if you set a “non existent option” like:

[root@snafu ~]# dnf config-manager --setopt foo=bar --save fubar-local-repo
Main config did not have a foo attr. before setopt
Main config did not have a foo attr. before setopt

You’ll see in the config like:

[fubar-local-repo]
name=Fubar Local Repository
#baseurl=file:///testrepo/
baseurl=ftp://fubar/pub/dnfrepo/
enabled=1
gpgcheck=0
priority = 11
foo = bar

“foo” is not a valid option so I’m not sure why it’s allowed but “dnf” won’t complain until you do something like (note I used “-v” for “verbose”):

[root@snafu ~]# dnf config-manager -v --dump-variables fubar-local-repo
Loaded plugins: builddep, config-manager, copr, debug, debuginfo-install, download, generate_completion_cache, needs-restarting, playground, repoclosure, repograph, repomanage, reposync
DNF version: 2.7.5
cachedir: /var/cache/dnf
Unknown configuration option: foo = bar in /etc/yum.repos.d/fubar-local.repo
arch = x86_64
basearch = x86_64
releasever = 28

I don’t know of a “verify” option you can use but I suspect one might exist.

And if you need to remove option “foo” the only way I know is to use a text editor 🙁

References

Almost of all of this is from doing it for years and web searches when I couldn’t figure something out. A great document I often overlook it:

https://media.readthedocs.org/pdf/dnf/stable/dnf.pdf

Here’s another site that’s a great listing of command examples:

https://www.ostechnix.com/dnf-command-examples-beginners/

Print Friendly

I prefer a PDF to print something like this.

  1. I have enough bandwidth it’s not a big deal to just re-download everything per server … this was an excellent opportunity to learn a lot about “dnf” :-) NOTE “smileys” don’t work in footnotes
  2. There are times like when I’ve been gone for a week on vacation this can easily be 400 to 500 M and across 5 or more fedora installs it does save download time.