How to build a local Yumrepo server on CentOS 6.5

Posted by paul on 2014.04.09

How to build a local Yumrepo server on CentOS 6.5

2014.04.09 Wed

Updated 2014.06.13: There was an error with how createrepo command was executed in earlier version. The command needs to be executed in each folder with rpms. It's been fixed.

This tutorial explains how to build a local Yumrepo server with CentOS 6.5 x86_64. This local Yumrepo server will cut a lot of time needed to install rpms on your CentOS servers. If you have more than a few CentOS servers in your LAN, you should set up a local Yumrepo server.


  1. My Yumrepo server (FQDN: yumrepo.base.loc) will be served by Apache. FTP is another option but I already have an underutilized Apache server. The Yumrepo server will need about 40-50GB HD space.
  2. The Apache's data directory on my server is at /data/www/. So RPMs in the Yumrepo server will be kept in /data/www/yumrepo/centos/.
  3. When I say install media it's either a physical DVD or an .iso file.
  4. You ssh into the Yumrepo server from your PC.
  5. Using test03.base.loc with CentOS 6.5 as a test client machine.

Install few rpms and prep Apache

  1. Install few rpms that are needed and prep Apache
  2. [[email protected] ~]# yum install httpd createrepo
    [[email protected] ~]# chkconfig httpd on
    [[email protected] ~]# service httpd start
  3. If you would like to change Apache's data directory from /var/www/html to /data/www/, edit /etc/httpd/conf/httpd.conf (back it up to /etc/httpd/conf/httpd.conf.orig before editing it) and change 2 lines.
  4. # Change 1: Old
    DocumentRoot "/var/www/html"
    # Change 1: New
    DocumentRoot "/data/www"
    # Change 2: Old
    <Directory "/var/www/html">
    # Change 2: New
    <Directory "/data/www">
  5. After saving httpd.conf, restart httpd service.

Create basic directory structure for files from install media

  1. For initial setup of Yumrepo server, you need to download a lot of files, like 30GB and more, from other Yumrepo mirror servers in the internet. Fortunately a lot of the files are already on your CentOS 6.5 install DVD. So you should copy files from the install media onto your Yumrepo server, BEFORE you start downloading files from public Yumrepo servers.
  2. Create directories to save rpm files. Complete directory structure will be created by rsync command later on but we need following directory created now so that we can copy install rpms from CentOS 6.5 DVD1 into the repo storage.
  3. mkdir -pv /data/www/yumrepo/centos/6.5/os/x86_64/
  4. If you have use 32bit install media, create following directory.
  5. mkdir -pv /data/www/yumrepo/centos/6.5/os/i386/

Copy files from install media to Yumrepo server

  1. Copy files from the CentOS 6.5 DVD x86_64 to Yumrepo-server:/data/www/yumrepo/centos/6.5/os/x86_64/. Following commands show how to do it if you happen to have an .iso file.
  2. mkdir /mnt/iso
    mount -t iso9660 -o loop ~/CentOS-6.5-x86_64-bin-DVD1.iso  /mnt/iso/
    cp -r /mnt/iso/* /data/www/yumrepo/centos/6.5/os/x86_64/
    umount /mnt/iso
  3. You should see /data/www/yumrepo/centos/6.5/os/x86_64/ with lots of rpms in there.
  4. If you have CentOS 6.5 i386 DVD in .iso file format, do the following to copy files over.
  5. mkdir /mnt/iso
    mount -t iso9660 -o loop ~/CentOS-6.5-i386-bin-DVD1.iso  /mnt/iso/
    cp -r /mnt/iso/* /data/www/yumrepo/centos/6.5/os/i386/
    umount /mnt/iso
  6. If you happen to have a physical DVD and your yumrepo server is a remote server (hopefully still within your local LAN), you can obviously insert the DVD into a drive in your local PC and copy files to yumrepo-server:/data/www/yumrepo/centos/6.5/os/x86_64/ or yumrepo-server:/data/www/yumrepo/centos/6.5/os/i386/.
  7. Check folder size after copying over the content of the CentOS 6.5 x86_64 DVD1 to the Yumrepo server.
  8. [[email protected] ~]# du -hs /data/www/yumrepo/centos/6.5/os/x86_64/
    4.2G    /data/www/yumrepo/centos/6.5/os/x86_64/

Rsync tip

Most yum mirror servers have same folder structure. But some may not so you should learn to use rsync to understand the folder structure of the mirror server you will download from.

  1. By visiting, you can find mirror servers you can download from. I will pick rsync:// for this tutorial. Run rsync command as shown below.
  2. [[email protected] ~]# rsync rsync://
    drwxrwxr-x        4096 2013/11/21 08:53:48 5.9
    drwxrwxr-x        4096 2013/10/19 04:17:56 5
    drwxrwxr-x        4096 2012/07/31 12:47:30 6.0
    drwxrwxr-x        4096 2012/07/31 12:47:15 6.1
    drwxrwxr-x        4096 2012/07/31 12:46:04 6.2
    drwxrwxr-x        4096 2013/07/23 18:54:50 6.3
    drwxrwxr-x        4096 2013/12/28 10:08:50 6.4
    drwxrwxr-x        4096 2013/12/21 09:05:34 6.5
    drwxrwxr-x        4096 2013/12/21 10:39:30 6
    drwxrwxr-x        4096 2013/11/07 10:21:56 HEADER.images
    drwxrwxr-x        4096 2005/06/12 08:56:32 build
    drwxrwxr-x        4096 2007/04/04 05:45:32 dostools
    drwxrwxr-x        4096 2011/12/09 22:50:04 extras
  3. You should see '6.5', which means you will download from rsync:// To see what's under 6.5 folder, just run following command. Note /* at the end.
  4. [[email protected] ~]# rsync rsync://*
    drwxrwxr-x        4096 2013/12/21 11:51:41 SCL
    drwxrwxr-x        4096 2013/12/13 15:03:57 centosplus
    drwxrwxr-x        4096 2013/11/29 13:20:12 contrib
    drwxrwxr-x        4096 2013/11/29 13:20:12 cr
    drwxrwxr-x        4096 2013/03/06 18:55:36 extras
    drwxr-xr-x        4096 2014/02/25 09:32:12 fasttrack
    drwxrwxr-x        4096 2013/11/30 02:10:06 isos
    drwxrwxr-x        4096 2013/11/27 17:36:14 os
    drwxrwxr-x        4096 2013/12/19 07:32:07 updates
    drwxrwxr-x        4096 2013/06/21 07:27:27 xen4

Download rpms with

  1. Once you've copied files from the DVDs or .iso files, you can start downloading files.
  2. Because rsyncing down rpms for CentOS 6.5 mirror takes so long (like 2-3 days with the 1MB cap), it's best to create and run a script ( to download the rpms.
  3. Now the basic rsync command would look like this:
  4. rsync -av rsync://* /data/www/yumrepo/centos/6.5/.
  5. You also need to rsync from rsync:// which actually has not much files inside.
  6. Note I use for example but you should pick a mirror server near your location by checking out Look for one that offers rsync.
  7. Before creating a script, check the mirror server is alive by running following command manually. You should see something like below. Hit Ctrl-C to cancel the download for now.
  8. [[email protected] ~]# rsync -av --bwlimit=1024  --exclude=debug --exclude=isos rsync://* /data/www/yumrepo/centos/6.5/
    receiving incremental file list
    # Ctrl-C to cancel the download for now.
  9. Create script, with following. Note some paths have trailing slash/dot and some don't. You should use trailing slash/dot exactly as shown below. If not careful, the files will end up in wrong places.
  10. #!/bin/bash
    # Rsync yum repo from to local HD
    SOURCE1=rsync://  #actually no real rpms here but copy it.
    #rsync command below
    rsync -av --bwlimit=1024  --exclude=repodata --exclude=debug --exclude=isos $SOURCE1 $TARGET/.
    rsync -av --bwlimit=1024  --exclude=repodata --exclude=debug --exclude=isos $SOURCE2 $TARGET/.
    exit 0
    1. bwlimit=1024: this caps the download speed to about 1MB. I strongly recommend this. Without this, your rsync command will consume all available bandwidth for hours/days. This will ruin internet use experience for all others.
    2. exclude: no need to download certain directories like 'debug' or 'isos' which contains .iso files.
    3. rsync://*: This is the source of the files. Note it starts with 'rsync'.
  11. Make executable and execute it.
  12. [[email protected] ~]# chmod 750
    [[email protected] ~]# ./
    receiving incremental file list
    6/SCL -> ../6.5/SCL/
    6/centosplus -> ../6.5/centosplus
    6/contrib -> ../6.5/contrib
    6/cr -> ../6.5/cr
    6/extras -> ../6.5/extras
    6/fasttrack -> ../6.5/fasttrack
    6/os -> ../6.5/os
    6/updates -> ../6.5/updates
    6/xen4 -> ../6.5/xen4
    sent 80 bytes  received 353 bytes  288.67 bytes/sec
    total size is 114  speedup is 0.26
    receiving incremental file list
  13. Close the Terminal window that you were using earlier. Open a new Terminal window and ssh into the Yumrepo server. You should see these folders.
  14. [[email protected] ~]# du -hs /data/www/yumrepo/centos/*
    4.0K    /data/www/yumrepo/centos/6
    124K    /data/www/yumrepo/centos/6.5
    [[email protected] ~]# du -hs /data/www/yumrepo/centos/6/*
    0   /data/www/yumrepo/centos/6/centosplus
    0   /data/www/yumrepo/centos/6/contrib
    0   /data/www/yumrepo/centos/6/cr
    0   /data/www/yumrepo/centos/6/extras
    0   /data/www/yumrepo/centos/6/fasttrack
    0   /data/www/yumrepo/centos/6/os
    0   /data/www/yumrepo/centos/6/SCL
    0   /data/www/yumrepo/centos/6/updates
    0   /data/www/yumrepo/centos/6/xen4
    [[email protected] ~]# du -hs /data/www/yumrepo/centos/6.5/*
    24K /data/www/yumrepo/centos/6.5/centosplus
    4.0K    /data/www/yumrepo/centos/6.5/contrib
    4.0K    /data/www/yumrepo/centos/6.5/cr
    4.0K    /data/www/yumrepo/centos/6.5/extras
    4.0K    /data/www/yumrepo/centos/6.5/fasttrack
    4.0K    /data/www/yumrepo/centos/6.5/os
    68K /data/www/yumrepo/centos/6.5/SCL
    4.0K    /data/www/yumrepo/centos/6.5/updates
    4.0K    /data/www/yumrepo/centos/6.5/xen4
    [[email protected] ~]#
  15. If you want to monitor the file size going up but don't want to keep hitting the keys, use 'watch' command. The 'watch' command repeats a given command every 2 seconds so you can use that command to monitor the file size in near real time. Because most of the files you download are in folder 6.5 and not 6, you can just monitor 6.5.
  16. watch 'du -s /data/www/yumrepo/centos/6.5/*'
  17. Here's what you will see after you run above command. You will see one of the numbers in the 1st column going up every few seconds. Hit Ctrl-C to quit 'watch' command.
  18. Every 2.0s: du -s /data/www/yumrepo/centos/6.5/*                          Mon Apr  7 15:08:08 2014
    2083196 /data/www/yumrepo/centos/6.5/centosplus
    4   /data/www/yumrepo/centos/6.5/contrib
    4   /data/www/yumrepo/centos/6.5/cr
    4   /data/www/yumrepo/centos/6.5/extras
    4   /data/www/yumrepo/centos/6.5/fasttrack
    4   /data/www/yumrepo/centos/6.5/os
    68  /data/www/yumrepo/centos/6.5/SCL
    4   /data/www/yumrepo/centos/6.5/updates
    4   /data/www/yumrepo/centos/6.5/xen4
  19. If you don't see any of the folders increasing in size, you need to kill the process, check for typos (or change the source server to another) and restart it.
  20. To stop the running:
    1. Find process number of with either of the 2 commands:
    2. [[email protected] ~]# ps ax
      [[email protected] ~]# ps ax | grep rsync
    3. You will see something like following.
    4. ...
      22700 pts/2    S      0:00 -bash
      23854 ?        S      0:00 pickup -l -t fifo -u
      23883 pts/1    S+     0:00 /bin/bash ./
      23886 pts/1    S+     0:00 rsync -av --bwlimit=1024 --exclude=debug --exclude=isos rsync:// /tmp/yum/
      23887 pts/1    S+     0:20 rsync -av --bwlimit=1024 --exclude=debug --exclude=isos rsync:// /tmp/yum/
      23953 pts/2    R+     0:00 ps ax
    5. To stop running, kill process 23886 (yours will be different). You can kill either 23886 or 23887 and the script will stop running.
    6. [[email protected] ~]# kill 23886
  21. It will take a good day or even 3 days to finish downloading. Be patient. Walk away. Just check every few hours or once a day to make sure it continues to run until completion.

Troubleshooting rsync issue

One downside of setting up your own yumrepo server is having to deal with other public yumrepo servers that are in flux. These are donated servers/bandwidth so the servers come and go. Or they can be down for extended period for maintenance. So you should be aware that the yum mirror server you pick may not be available sometimes or go offline completely (although unlikely).

    Managing Headers with createrepo command

    1. Once the download is completed, you can move onto running 'createrepo' command.
    2. The createrepo command consolidates headers in compressed XML files. It creates the headers that the yum command needs to specify dependencies. It needs to be executed every time new rpms are downloaded. Here's the basic command, but don't execute it yet.
    3. [[email protected] ~]# createrepo /data/www/yumrepo/centos
    4. Depending on your server's spec, it will take some time. My Yumrepo server is actually a KVM guest on a low end server, "HP ProLiant N40L with AMD Turion II Neo N40L 1.5GHz". The KVM is allocated 1GB of RAM and shares the CPU time with a few other KVM guests so it's not exactly a fast server.
    5. Createrepo command needs to be executed multiples times, in each folder. For this reason, it's best to first create a script to run createrepo command multiple times.

    1. Create with following line and save/close it.
    2. #!/bin/bash
    3. Next, find folders with rpms and add the list to with following commands.
    4. [[email protected] ~]# find /data/www/yumrpms/ -name "x86_64" >>
      [[email protected] ~]# find /data/www/yumrpms/ -name "i386" >>
      [[email protected] ~]# more
      [[email protected] ~]#
    5. Use sed command to add 'createrepo' command to the beginning of the lines that need it. Note each line (except for 1st line) now has 'createrepo' at beginning.
    6. [[email protected] ~]# sed -i "s/\/data/createrepo \/data/g"
      [[email protected] ~]# more
      createrepo /data/www/yumrpms/centos/6.5/centosplus/x86_64
      createrepo /data/www/yumrpms/centos/6.5/extras/x86_64
      createrepo /data/www/yumrpms/centos/6.5/cr/x86_64
    7. Give execute permission to and run it. First execution of 'createrepo' command will take a while.
    8. [[email protected] ~]# chmod 750
      [[email protected] ~]# ./
      Spawning worker 0 with 54 pkgs
      Workers Finished
      Gathering worker results
      Saving Primary metadata
      Saving file lists metadata
      Saving other metadata
      Generating sqlite DBs
      Sqlite DBs complete
      Spawning worker 0 with 56 pkgs

    Combine rsync and createrepo in 1 script

    1. In order to keep up with new rpms that are every few days/weeks/months, you should create a script that automatically downloads the rpms and then run createrepo command. Here's the final version of When you execute, rpms will be rsynced down and than will be created and executed. runs createrepo command in the subfolders. Again, remember to change with server of your choice.
    2. #!/bin/bash
      # This script rsyncs rpms down to the local Yumrepo server.
      # It then creates a separate shell script (
      # which runs createrepo in necessary folders.
      # variables
      # where rpms are kept on the local server
      # script
      ### Rsync rpms down
      /usr/bin/rsync -av --bwlimit=1024 --exclude=repodata --exclude=debug --exclude=isos --delete $SOURCE1 $TARGET/.
      /usr/bin/rsync -av --bwlimit=1024 --exclude=repodata --exclude=debug --exclude=isos --delete $SOURCE2 $TARGET/.
      ### Empty out $CREATE in case it exists. And create basic template of $CREATE.
      cat /dev/null > $CREATE
      cat < $CREATE
      # This script runs createrepo command in all directories with .rpm files.
      # Created: `date`
      find /data/www/yumrpms/ -name "x86_64" >> $CREATE
      find /data/www/yumrpms/ -name "i386" >> $CREATE
      #find /data/www/yumrpms/ -name "noarch" >> $CREATE
      ### Insert 'createrepo' OR 'createrepo --update' in $CREATE.
      # Uncheck only one of the 2 following sed commands.
      # 1.
      # If you are creating a new Yumrepo server, uncheck following line.
      # sed -i "s/\/data/createrepo \/data/g" $CREATE
      # 2.
      # If you are just doing incremental download of few rpms, uncheck following line. It speeds up createrepo command.
      sed -i "s/\/data/createrepo --update \/data/g" $CREATE
      ### Execute $CREATE.
      chmod 750 $CREATE
      /bin/bash $CREATE
      exit 0
    3. Note in, each createrepo command actually has "createrepo --update /data/..." instead of "createrepo /data/...". Using -–update option with createrepo command speeds up the createrepo process. You can use --update option only if the initial createrepo was done once already.
    4. Set the script to run once a week by adding following line in /etc/crontab as shown, as root. It will run every Mon 2:59AM.
    5. 59 2 * * 1 root /root/bin/
    6. You can run manually when you want to propagate newly released RPMs to systems in the LAN without waiting for Mon night update.

    Roll out to production

    Back up Yumrepo server

    You have downloaded/copied nearly 30GB of data from dvd/internet. So it would be a good idea to backup /data/www/yumrpms/ off to another local server/storage.

    Test with a client

    1. On test03 (a CentOS machine used for testing), rename /etc/yum.repos.d/CentOS-Base.repo as /etc/yum.repos.d/CentOS-Base.repo.orig. This basically tells your CentOS server not to use the Yum servers on the internet.
    2. [[email protected] ~]# cd /etc/yum.repos.d/
      [[email protected] ~]# mv CentOS-Base.repo CentOS-Base.repo.orig
    3. On test03, create /etc/yum.repos.d/Yumlocal-Base.repo with following content. Note my local Yum Repo server has the FQDN of yumrepo.base.loc.
    4. [base]
      name=CentOS-$releasever - Base
      #released updates
      name=CentOS-$releasever - Updates
      #additional packages that may be useful
      name=CentOS-$releasever - Extras
      #additional packages that extend functionality of existing packages
      name=CentOS-$releasever - Plus
    5. Check you have following files in /etc/yum.repos.d/.
    6. [[email protected] ~]# ls /etc/yum.repos.d/ | sort
    7. Now your test03 is ready for using the Yumrepo server on the yumrepo.base.loc. Run yum clean all and test installing httpd. If you see following, it's working.
    8. [[email protected] ~]# yum clean all
      Loaded plugins: fastestmirror, security
      Cleaning repos: base extras updates
      Cleaning up Everything
      [[email protected] ~]#
      [[email protected] ~]# yum install httpd
      Loaded plugins: fastestmirror, security
      Determining fastest mirrors
      base            | 3.7 kB     00:00
      base/primary_db         | 4.4 MB     00:00
      extras      | 3.4 kB     00:00
      extras/primary_db   |  19 kB     00:00
      updates     | 3.4 kB     00:00
      updates/primary_db      | 2.5 MB     00:00
      Setting up Install Process
      Resolving Dependencies
      --> Running transaction check
      ---> Package httpd.x86_64 0:2.2.15-29.el6.centos will be updated
      ---> Package httpd.x86_64 0:2.2.15-30.el6.centos will be an update
      --> Processing Dependency: httpd-tools = 2.2.15-30.el6.centos for package: httpd-2.2.15-30.el6.centos.x86_64
      --> Running transaction check
      ---> Package httpd-tools.x86_64 0:2.2.15-29.el6.centos will be updated
      ---> Package httpd-tools.x86_64 0:2.2.15-30.el6.centos will be an update
      --> Finished Dependency Resolution
    9. Note that if you ever want to stop using your own Yumrepo server and return to using the public Yum repo servers, just (1) rename CentOS-Base.repo.orig --> CentOS-Base.repo & (2) rename Yumlocal-Base.repo --> Yumlocal-Base.repo.bak.
    10. IMPORTANT: Sometimes after you run 'yum update', the file /etc/yum.repos.d/CentOS-Base.repo gets recreated. So you should remember to check content of /etc/yum.repos.d/ to check CentOS-Base.repo does not exist after running 'yum update'. To automate this, use a script to run 'yum update' or use SaltStack to make sure the file does not exist.


    Configure your local CentOS servers to start using your local Yumrepo server by updating content of /etc/yum.repos.d/ on all of them.

    [[email protected] ~]# cd /etc/yum.repos.d/
    [[email protected] ~]# mv CentOS-Base.repo CentOS-Base.repo.orig
    [[email protected] ~]# yum clean all; yum history new
    [[email protected] ~]# yum update

    When switching between public Yumrepo server and your private Yumrepo server, run yum history new command once. This will keep error message Warning: RPMDB altered outside of yum from appearing. That's it.