{"id":1318,"date":"2024-02-25T21:34:00","date_gmt":"2024-02-25T21:34:00","guid":{"rendered":"https:\/\/haxed.me.uk\/?p=1318"},"modified":"2024-02-25T22:35:14","modified_gmt":"2024-02-25T22:35:14","slug":"hosting-a-centos-stream-9-repo-locally-in-your-lab","status":"publish","type":"post","link":"https:\/\/haxed.me.uk\/index.php\/2024\/02\/25\/hosting-a-centos-stream-9-repo-locally-in-your-lab\/","title":{"rendered":"Hosting a CentOS Stream 9 Repo Locally in your Lab"},"content":{"rendered":"\n<p>I have been doing a lot of lab work lately and it has occurred to me that it would be pretty cool to run a 2 vcpu vm with 2gb ram, minimal resources in the lab, to host our own x86 repository for my favourite OS of choice, centos. It&#8217;s really easy to do too thanks to yum-utils.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n# cat make-centos9-repo-server.sh\nvirt-install --name centos9-repo-mirror --memory 2048 --vcpus 2 --disk=size=500,backing_store=\/var\/lib\/libvirt\/images\/CentOS-Stream-GenericCloud-9-latest.x86_64.qcow2 --cloud-init user-data=.\/cloud-init.yaml,meta-data=.\/centos9-repo-server.yaml,disable=on --network bridge=virbr0 --osinfo=centos-stream9 --noautoconsole\n<\/pre><\/div>\n\n\n<p>Using my current lab template above, I simply alter a few things like name, vcpus, and increase the initial disk space to 500GB. Which should be ample for now.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the repository mirrors<\/h2>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nsudo dnf install yum-utils\n\n#create repo directory path and subdirectory structure\nmkdir -p \/var\/www\/repos\/centos-stream\/9\/x86_64\/os\n\nchmod -R 755 \/var\/www\/repos\n\n# copy from official repository\nreposync -p \/var\/www\/repos\/centos-stream\/9\/x86_64\/os\/ --repo=baseos --download-metadata\nreposync -p \/var\/www\/repos\/centos-stream\/9\/x86_64\/os\/ --repo=appstream --download-metadata\nreposync -p \/var\/www\/repos\/centos-stream\/9\/x86_64\/os\/ --repo=extras-common --download-metadata \n<\/pre><\/div>\n\n\n<p>Configuring a cronjob to automatically resync the repo daily<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nvi \/etc\/cron.daily\/update-repo\n# create new\n\n#!\/bin\/bash\n\nVER='9'\nARCH='x86_64'\nREPOS=(baseos appstream extras-common)\n\nfor REPO in ${REPOS&#x5B;@]}\ndo\n    reposync -p \/var\/www\/repos\/centos-stream\/${VER}\/${ARCH}\/os\/ --repo=${REPO} --download-metadata --newest-only\ndone\nsudo restorecon -r \/var\/www\/repos\/\n\n# exit vim :wq and chmod the cronfile for good measure\nchmod 755 \/etc\/cron.daily\/update-repo \n<\/pre><\/div>\n\n\n<p>Then we install the httpd server and configure it for this path<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nvi \/etc\/httpd\/conf.d\/repos.conf\n# create new\n\nAlias \/repos \/var\/www\/repos\n&amp;lt;directory \/var\/www\/repos&gt;\n    Options +Indexes\n    Require all granted\n&amp;lt;\/directory&gt;\n\n#exit vim and restart the httpd with the new root repo\nsystemctl restart httpd \n<\/pre><\/div>\n\n\n<p>Finally we add firewall rule<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nfirewall-cmd --add-service=http --permanent\nsystemctl restart firewalld\n<\/pre><\/div>\n\n\n<p>All done. Now we can configure the local server with our golden image cloud image we&#8217;re using to boot from libvirt with our own local repo. Ideally we&#8217;d also have a local dns server so we can run mirror.some.tld or similar. In this case the ip address will for now suffice, with a hostname in \/etc\/hosts of the golden image like local-mirror &lt;centos9-local-repo-ip>, instead so it looks pretty and recognisable in the repo file.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nvi \/etc\/yum.repos.d\/centos.repo\n# change to local mirror server\n\n&#x5B;baseos]\nname=CentOS Stream $releasever - BaseOS\n#metalink=https:\/\/mirrors.centos.org\/metalink?repo=centos-baseos-$stream&amp;amp;arch=$basearch&amp;amp;protocol=https,http\nbaseurl=http:\/\/local-mirror\/repos\/centos-stream\/$releasever\/$basearch\/os\/baseos\/\ngpgkey=file:\/\/\/etc\/pki\/rpm-gpg\/RPM-GPG-KEY-centosofficial\ngpgcheck=1\nrepo_gpgcheck=0\nmetadata_expire=6h\ncountme=1\nenabled=1\n\n&#x5B;appstream]\nname=CentOS Stream $releasever - AppStream\n#metalink=https:\/\/mirrors.centos.org\/metalink?repo=centos-appstream-$stream&amp;amp;arch=$basearch&amp;amp;protocol=https,http\nbaseurl=http:\/\/local-mirror\/repos\/centos-stream\/$releasever\/$basearch\/os\/appstream\/\ngpgkey=file:\/\/\/etc\/pki\/rpm-gpg\/RPM-GPG-KEY-centosofficial\ngpgcheck=1\nrepo_gpgcheck=0\nmetadata_expire=6h\ncountme=1\nenabled=1\n\n# vi \/etc\/yum.repos.d\/centos-addons.repo\n# change to local mirror server\n\n&#x5B;extras-common]\nname=CentOS Stream $releasever - Extras packages\n#metalink=https:\/\/mirrors.centos.org\/metalink?repo=centos-extras-sig-extras-common-$stream&amp;amp;arch=$basearch&amp;amp;protocol=https,http\nbaseurl=http:\/\/local-mirror\/repos\/centos-stream\/$releasever\/$basearch\/os\/extras-common\/\ngpgkey=file:\/\/\/etc\/pki\/rpm-gpg\/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512\ngpgcheck=1\nrepo_gpgcheck=0\nmetadata_expire=6h\ncountme=1\nenabled=1\n\n\n<\/pre><\/div>\n\n\n<p>Finally clean and re-update yum to test config change<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ndnf clean all\ndnf repolist \n<\/pre><\/div>\n\n\n<p>If you are insisting on running selinux like me, make sure you allow filegetattr;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;adam@centos9-repo-server appstream]$ sudo audit2allow -a -M filegetattr\n******************** IMPORTANT ***********************\nTo make this policy package active, execute:\n\nsemodule -i filegetattr.pp\n\n&#x5B;adam@centos9-repo-server appstream]$ semodule -i filegetattr.pp\nlibsemanage.semanage_create_store: Could not read from module store, active modules subdirectory at \/var\/lib\/selinux\/targeted\/active\/modules. (Permission denied).\nlibsemanage.semanage_direct_connect: could not establish direct connection (Permission denied).\nsemodule:  Could not connect to policy handler\n&#x5B;adam@centos9-repo-server appstream]$ sudo semodule -i filegetattr.pp\n\n<\/pre><\/div>\n\n\n<p>It wouldn&#8217;t go amiss to tag the files either however in this case chcon isn&#8217;t necessary because the \/var\/www context already has the correct mask by default in selinux. \ud83d\ude00<\/p>\n\n\n\n<p>As it turns out you also need read, as well as getattr to actually download the packages (getattr is needed for listing them i.e. ls)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n$ sudo audit2allow -a\n\n\n#============= httpd_t ==============\n\n#!!!! This avc is allowed in the current policy\nallow httpd_t var_t:file getattr;\nallow httpd_t var_t:file read;\n&#x5B;adam@centos9-repo-server appstream]$ sudo audit2allow -a -M httpdread.pp\n&#x5B;adam@centos9-repo-server appstream]$ sudo semodule -i httpdread.pp\n\n<\/pre><\/div>\n\n\n<p>Once again we retry. OK, turns out we do need to set the unconfined files\/folder that were written; which can be done like<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n sudo restorecon -r \/var\/www\/repos\/\n<\/pre><\/div>\n\n\n<p>I guess we&#8217;ll add this restorecon -r \/var\/www\/repos\/ to our cronjob for good measure to make sure the context is right.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have been doing a lot of lab work lately and it has occurred to me that it would be pretty cool to run a 2 vcpu vm with 2gb ram, minimal resources in the lab, to host our own &hellip; <a href=\"https:\/\/haxed.me.uk\/index.php\/2024\/02\/25\/hosting-a-centos-stream-9-repo-locally-in-your-lab\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1318","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/posts\/1318","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/comments?post=1318"}],"version-history":[{"count":6,"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/posts\/1318\/revisions"}],"predecessor-version":[{"id":1328,"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/posts\/1318\/revisions\/1328"}],"wp:attachment":[{"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/media?parent=1318"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/categories?post=1318"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/haxed.me.uk\/index.php\/wp-json\/wp\/v2\/tags?post=1318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}