Install your own local Repo server on CentOS 7

This post is for installing your own Linux repository server, running on CentOS 7 to host CentOS 7 repos. Additional EL repos (CentOS 5/6, RHEL, Scientific Linux, etc) are definitely possible to store here, as well as a Debian based repos (Debian, Ubuntu, etc), though not quite as easy. Thus, I will be focusing only on CentOS 7 with this guide. In short, we will be using createrepo to generate our repository metadata, nginx to serve the files over HTTP, and using rsync to automatically pull packages from a public repo server. From there, we only have to update the baseurl(s) of the repo files on our CentOS 7 client servers, and profit!

In my setup I have SELinux disabled (sed -i /etc/selinux/config -r -e 's/^SELINUX=.*/SELINUX=disabled/g'). If you disable selinux (or firewalld), you do so at your own risk. It is not advisable to do either if your server is directly accessible on the internet (this one should not be), so please do so at your own risk! At the bottom of this post I've included the simple rules needed for firewalld (on a CentOS 7.2 minimal install, you will need to install firewalld as firewalld is no longer included in the CentOS 7 default minimal install).

Let's Get Started!

1.) updates and requisites:
yum -y install createrepo epel-release firewalld rsync && yum -y install nginx
yum -y update && systemctl reboot
2.) create directories and initialize repos:
mkdir -p /var/www/html/repos/centos/7/{os/x86_64,updates/x86_64}   # Base and Update Repos
mkdir -p /var/www/html/repos/epel/7/x86_64   # EPEL Repo
createrepo /var/www/html/repos/centos/7/os/x86_64/   # Initialize CentOS Base Repo
createrepo /var/www/html/repos/centos/7/updates/x86_64/   # Initialize CentOS Update Repo
createrepo /var/www/html/repos/epel/7/x86_64/   # Initialize EPEL 7 Repo
3.) configure nginx:
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig
vi /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/;

events {
    worker_connections 1024;

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

vi /etc/nginx/conf.d/repo.conf
server {
    listen  80;
    server_name  localhost;
    root  /var/www/html/repos;

    location  / {
        autoindex  on;


This is just a basic nginx config, that will allow for directory browsing from a web browser. Feel free to add any additional parameters you'd like, such as error_page.

4.) initial repo clone:

In this step we will clone done all the available packages and files from an existing repo mirror. The mirror I am using for CentOS-Base repos is from, which I have found to be reliable and fast. For EPEL, I am using Feel free to use any other mirror you'd like. You can find a list of all the CentOS repo mirros here.

Each of these commands may take up to an hour (or more) to run, based on your internet download speed. I suggest opening 3 terminals and running all 3 at the same time, and walk away for about 30 minutes.

rsync -avz --exclude='repo*' rsync:// /var/www/html/repos/centos/7/os/x86_64/   # CentOS Base Repo
rsync -avz --exclude='repo*' rsync:// /var/www/html/repos/centos/7/updates/x86_64/   # CentOS Update Repo
rsync -avz --exclude='repo*' --exclude='debug' rsync:// /var/www/html/repos/epel/7/x86_64/   # EPEL 7 Repo

Once all 3 commands have run, you should have several thousand packages in your repo directories. Next we need to update the repo metadata by running:

createrepo --update /var/www/html/repos/centos/7/os/x86_64/   # CentOS Base Repo
createrepo --update /var/www/html/repos/centos/7/updates/x86_64/   # CentOS Update Repo
createrepo --update /var/www/html/repos/epel/7/x86_64/   # EPEL 7 Repo

At this point, we now have a work repository!

5.) automate repo mirror updating:

What good is a repo if it's not kept up to date? We simple need to create a few crontab entries to run these commands to ensure we are pulling any new packages and updating the metadata. I choose to do it once a day, in the early morning. You can change the cron rules to run it whenever. I give 1h 15m between each rsync pull, just to make sure one completes before the next starts (not that that really matters). Here are my rules:

crontab -e
15 1 * * * /usr/bin/rsync -avz --delete --exclude='repo*' rsync:// /var/www/html/repos/centos/7/os/x86_64/
30 2 * * * /usr/bin/rsync -avz --delete --exclude='repo*' rsync:// /var/www/html/repos/centos/7/updates/x86_64/
45 3 * * * /usr/bin/rsync -avz --delete --exclude='repo*' --exclude='debug' rsync:// /var/www/html/repos/epel/7/x86_64/

0 5 * * * /usr/bin/createrepo --update /var/www/html/repos/centos/7/os/x86_64/
15 5 * * * /usr/bin/createrepo --update /var/www/html/repos/centos/7/updates/x86_64/
30 5 * * * /usr/bin/createrepo --update /var/www/html/repos/epel/7/x86_64/

As you can see, I am updating CentOS Base Repo at 1:15am, CentOS Update Repo at 2:30am, and EPEL 7 Repo at 3:45am. Finally, I am updating all 3 repo's metadata at 5:00am, 5:15am, and 5:30am, respectively. Should have more than enough time for each command to run and finish before the next starts.

6.) client config:

Now that our local repo mirror is set up and running, we just need to update our CentOS 7 clients to point to these repos and we'll be done. To do this, we need to edit the .repo file and update the baseurl.

vi /etc/yum.repos.d/CentOS-Base.repo
name=CentOS-$releasever - Base
baseurl=http://repo.domain.local/centos/$releasever/os/$basearch/   # UPDATE "repo.domain.local" TO YOUR NEW REPO SERVER'S URL
#released updates

name=CentOS-$releasever - Updates
baseurl=http://repo.domain.local/centos/$releasever/updates/$basearch/   # UPDATE "repo.domain.local" TO YOUR NEW REPO SERVER'S URL

vi /etc/yum.repos.d/epel.repo
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=http://repo.domain.local/epel/7/$basearch/   # UPDATE "repo.domain.local" TO YOUR NEW REPO SERVER'S URL

Repo files are now updated. Let's clean up our local yum cache, and make sure everything is working.

yum clean all
yum repolist

As long as yum repolist runs and you get no errors, that means everything is working as expected!

7.) start services and configure firewalld:
systemctl enable nginx.service && systemctl enable firewalld.service   # Enable services
systemctl start firewalld.service   # Ensure firewalld is running
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
systemctl reboot   # System reboot

And we're done!

In case you are curious what the difference between CentOS Base and CentOS Update Repos are, I didn't know either for the longest time. The current Base Repo is a direct copy of a certain release, so it contains all the files located on the iso image you download when you download CentOS full. The Update Repo contains any package updates since the last minor release of CentOS was released. For example, the current Base Repo (at the time of writing this) is for CentOS 7.2, and the Updates Repo contains any package updates since CentOS 7.2 was finalized. Once CentOS 7.3 is release, any packages listed in the Update Repo will move to the Base Repo, and the process starts again. At least, that's the way I understand it.

So let me know what you think!

Related Posts

Share on: Twitter | Facebook | Google+ | Email

comments powered by Disqus