NOTE: This should work on CentOS 6 / RHEL 6 as well.

My company has several disconnected (dark) labs. These labs have no internet access and only have access to a local network that several machines are on. This can quickly become a nightmare when trying to patch the systems, install packages, etc. Here is an outline on how to patch a disconnected or air-gapped system using CentOS 7. This should work for Red Hat or any Red Hat variant that is using yum (not tested with dnf).

For this to work, we will need one connected system with a good amount of free disk space. From that system, we will sync the packages, build the repos and share out those repositories with the other disconnected systems via HTTP (apache).

Install the Required Packages

We will need some utilities in order to sync and work with repos on our connected system. Let's install a couple required packages.

# yum -y install yum-utils createrepo

Sync Repository Data to a Local Directory

Now, we will sync the repo data to the /var/www/html directory. We are using the /var/www/html directory because later we will install apache in order to serve the repo to clients. We will sync and create a repo for base, extras and updates. You can choose whatever you like.

# reposync --gpgcheck -l --repoid=base --download_path=/var/www/html --downloadcomps --download-metadata
# reposync --gpgcheck -l --repoid=extras --download_path=/var/www/html --downloadcomps --download-metadata
# reposync --gpgcheck -l --repoid=updates --download_path=/var/www/html --downloadcomps --download-metadata

NOTE: This initial sync will take some time. At the time of writing there were approx 10,000+ rpms to download just in the base repo.

Create a Repository

Now create a repo out of the downloaded data.

# createrepo -v /var/www/html/base/
# createrepo -v /var/www/html/extras/
# createrepo -v /var/www/html/updates/

Install and Configure Apache to Serve our Repository

Now let's install apache and configure it to share out the repos.

# yum -y install httpd

Edit the /etc/httpd/conf/httpd.conf file and edit the following lines. For <IPADDR> substitute the ip address of your system.

ServerAdmin root@<IPADDR>
DocumentRoot "/var/www/html/"
ServerName <IPADDR>:80

Because we created all the files before we installed apache, the SELinux context of all the directories is going to be wrong and SELinux will block any attempt to access them via HTTP. Let's fix that by restoring the correct context using restorecon.

# restorecon -R /var/www/html/*

Now ensure you didn't make any mistakes by checking the syntax of the configuration file.

# httpd -t
Syntax OK

Let's start the HTTP service.

# systemctl start httpd.service

Enable the HTTP server on boot.

# systemctl enable httpd.service

NOTE: You have to ensure your firewall allows traffic on port 80.

If you are using iptables:

# iptables -I INPUT -p tcp --dport 80 -j ACCEPT

If you are using firewalld:

# firewall-cmd --zone=public --add-port=80/tcp --permanent
# firewall-cmd --reload

TEST: You should now be able to access the repomd.xml file from your browser at the following URL (remember to substitute your IP address).

http://<IPADDR>/base/repodata/repomd.xml

If the test above was successful and you saw the xml file, let's create the repo on the client machine(s).

Disable All Default Repositories on Local Machine

MOVE TO THE CLIENT MACHINE

Most systems by default have a "CentOS-Base.repo" file that does not have the "enabled=1" option in it. So run the following command to ensure that repo is disabled.

sed -i '/gpgcheck/a enabled=0' /etc/yum.repos.d/CentOS-Base.repo

Depending on what options you chose for installation, other repos may have been installed. It is a good idea to disable all repos to avoid yum errors or timeouts. Use the sed command to replace "enabled=1" with "enabled=0" in all of the installed repos.

sed -i 's/enabled=1/enabled=0/g' /etc/yum.repos.d/*

You can now check to ensure all repos are disabled by running "yum clean all". You should get output saying there are no enabled repos.

yum clean all
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
There are no enabled repos.

Alternatively, you can check using "yum repolist all". All repos should show disabled on the right column.

yum repolist all
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
repo id repo name status
C7.0.1406-base/x86_64 CentOS-7.0.1406 - Base disabled
C7.0.1406-centosplus/x86_64 CentOS-7.0.1406 - CentOSPlus disabled
C7.0.1406-extras/x86_64 CentOS-7.0.1406 - Extras disabled
.... OUTPUT TRUNCATED...

Configure New Local Repository on Clients

To add the new repo on the client, create the following file in the /etc/yum.repos.d/ directory. You can call it whatever you like, but it makes sense to call it something like offline.repo. Remember to insert the IP address of the system running HTTP for <IPADDR>.

# cat offline.repo
[CentOS7-Base]
name=CentOS7 Base
baseurl=http://<IPADDR>/base/
enabled=1
gpgcheck=0
[CentOS7-Updates]
name=CentOS7 Updates
baseurl=http://<IPADDR>/updates/
enabled=1
gpgcheck=0
[CentOS7-Extras]
name=CentOS7 Extras
baseurl=http://<IPADDR>/extras/
enabled=1
gpgcheck=0

Clean the client's yum database:

# yum clean all

Run First Update with New Local Repository

Now run your updates and Bob's your uncle....

[root@centos-client yum.repos.d]# yum update -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package NetworkManager.x86_64 1:1.12.0-6.el7 will be updated
---> Package NetworkManager.x86_64 1:1.12.0-8.el7_6 will be an update
---> Package NetworkManager-libnm.x86_64 1:1.12.0-6.el7 will be updated
---> Package NetworkManager-libnm.x86_64 1:1.12.0-8.el7_6 will be an update
---> Package NetworkManager-team.x86_64 1:1.12.0-6.el7 will be updated
---> Package NetworkManager-team.x86_64 1:1.12.0-8.el7_6 will be an update
---> Package NetworkManager-tui.x86_64 1:1.12.0-6.el7 will be updated
...OUTPUT TRUNCATED...

Now, we are unable to bring the connected system into the lab. So what I do it sync the rpm data to a USB hard drive. I then scan the USB hard drive for viruses, etc. Then I bring that USB hard drive into the lab where I have a server configured with apache per above. I then copy the data, build the repos (createrepo) and serve out the updates. Every once in a while I bring the USB drive out and download the new updates, and around we go.

Conclusion

In this article we discussed a good way to update a local only (air-gapped) system or network of systems that have no internet access. Using the supplied yum utilities we were able to create a local repository to serve to our clients.

If anyone has a better way to accomplish this please sound off in the comments.

Resources and Links