离线yum源搭建实操:从ISO挂载到reposync同步的完整指南

发布时间:2026/10/19 9:16:29
离线yum源搭建实操:从ISO挂载到reposync同步的完整指南 接到一个活儿给内网的一批机器装软件。机器倒是不少问题是它们全在一个隔离环境里外网是彻底不通的。一开始没多想直接yum install一把梭结果自然是报错一堆说什么Cannot find a valid baseurl for repo: base。那一刻我就知道得老老实实给这批 CentOS 配一个离线 yum 源。说实话离线配 yum 源这事儿听起来像是最基础不过的运维操作但真上手的时候坑一个接一个。光是把 ISO 挂上去、写个 repo 文件你以为就完事儿了依赖缺失、GPG 签名、缓存不刷新、路径写错、权限不对哪一个都能让你折腾半天。这篇就当是我自己的踩坑记录加实操总结把离线 yum 源的几种做法、原理、参数细节、排错经验一次说清楚希望能帮到同样被内网环境折磨的运维同学。1. 离线 yum 源到底怎么选先想清楚再动手1.1 为什么会有离线 yum 源的需求很多人觉得 yum 源就是一个配置文件的事儿默认指向互联网仓库就行。但在实际生产环境里情况往往不是这样安全隔离区出于安全合规要求机器放在隔离网段物理上就没有外网通路。内网专属软件有些内部开发的 rpm 包、定制内核、私有驱动需要统一放到一个仓库里供全内网使用。版本可控线上环境追求稳定不能随便从外网拉到新版本导致依赖漂移固定版本的内网源反而是最佳选择。批量装机场景自动化装机比如用 kickstart的时候安装源必须指向本地可访问的位置不然整个流程直接卡死。在这些场景里yum 源已经不只是装个软件那么简单它实际上承担了内网软件分发、版本管理、依赖解析的基础设施角色。所以离线 yum 源从来不是把 repo 文件改个地址那么草率而是要先想清楚规模和更新频率再选具体的实现方式。1.2 三种主流离线源方案对比我自己的经验离线 yum 源大致可以分成三条路线方案原理适用场景优点缺点ISO 镜像挂载把 CentOS 安装光盘 ISO 挂载到某个目录直接把该目录作为 base 仓库单机或少量机器应急零成本、最快、不需要额外工具包不全只有安装镜像自带的包扩展源epel 等完全没有reposync 全量同步在有外网的机器上用 reposync 把远端仓库同步到本地目录再通过 HTTP/NFS 共享给内网中大规模集群、需要完整仓库仓库内容完整、可定期增量更新体验和在线源几乎一致需要一台能访问外网的同步机且磁盘占用很大createrepo 自建仓库收集散落的 rpm 包用 createrepo 生成元数据做成自定义私有仓库内部软件包管理、离线包补充灵活、能管内部自研包和第三方离线包依赖关系需要自己把控元数据生成有学习成本我自己在实际项目中用得最多的是第二种也就是 reposync 方案。因为生产环境里的内网集群动辄几十上百台机器ISO 源根本喂不饱依赖稍微绕一点就缺包。而第三种更适合小规模、特定包的场景。但不管哪种方案最终落在客户端眼里都只是几个 repo 文件的指向问题。所以别急着动手先判断好自己的规模再决定用哪种方式搭。1.3 先理解 yum 的工作机制少走一半弯路yum以及它的继任者 dnf本质上是一个包管理器 依赖解析器。它的工作流程大致是读取/etc/yum.repos.d/目录下所有.repo文件。根据每个 repo 文件里的baseurl或mirrorlist去获取仓库元数据repodata 目录下的repomd.xml。解析元数据里的包列表和依赖关系。安装软件时在仓库元数据里做依赖解析找到所有需要的 rpm 包。下载并安装默认还会做 GPG 签名校验。所以离线源的核心说白了就是让 yum 在本地也能找到一份合法的仓库元数据。repomd.xml这个文件就是仓库的目录索引yum 看到它才会认为这个目录是一个有效仓库。很多人把一堆 rpm 扔到一个目录里然后直接写 repo 文件结果 yum 报 not a valid repository就是因为没有生成元数据。这一点理解了后面所有配置都会顺理成章。2. 写 repo 文件之前先把参数机制吃透2.1 一个标准 repo 文件长什么样先看一个最典型的本地源配置[base] nameCentOS-$releasever - Base baseurlfile:///mnt/cdrom enabled1 gpgcheck0这段配置看着简单但我见过无数人在这里踩坑。baseurl指向的路径必须是仓库元数据所在目录的上一级也就是说baseurlfile:///mnt/cdrom时/mnt/cdrom/repodata/repomd.xml必须存在。如果路径指到了/mnt/cdrom/repodata那 yum 反而找不到因为它要找的是repodata/repomd.xml这个相对路径。enabled1表示启用这个仓库如果写成 0那这个仓库就是废的。gpgcheck我建议在离线内网环境下直接设为 0省去一大堆签名导入的麻烦。如果非要开就得把公钥导进去否则装包时报Public key for xxx.rpm is not installed又是额外的一顿折腾。注意file://协议是本地路径后面跟的是绝对路径。用网络共享时可以写成http://192.168.x.x/centos或nfs://192.168.x.x/centos协议头千万别写漏。2.2 变量与通配符的实际用法很多人不知道 repo 文件里支持$releasever、$basearch这些内置变量。比如baseurlfile:///mnt/BaseOS但如果你的挂载目录是固定的直接用绝对路径更稳妥。我自己一开始图省事写成baseurlfile:///mnt/$releasever/BaseOS结果因为/etc/yum.conf里没有正确识别 releasever路径解析出来是错的直接报错。后来我学乖了离线源这种场景能不用变量就不用变量路径写死反而最可靠。还有一个小细节repo 文件里的name字段只是给人看的说明不影响功能。但[repo id]这个中括号里的标识符必须是全局唯一的两个 repo 文件如果使用了相同的 repo idyum 会随机取一个行为极其诡异。排查过一例就是多个 repo 文件里都写了[base]导致源时好时坏。2.3 GPG 校验开还是不开我曾经在一个项目里因为怕不安全特意在离线源上开了gpgcheck1然后辛辛苦苦把公钥导入。结果一段时间后仓库里加入了一批第三方 rpm没有用同一把 GPG 私钥签名所有机器安装时全部报错差点把发布流程卡死。所以我的建议是在内网离线源场景下gpgcheck0是更实际的选择。离线环境的包来源本身是可控的要么来自官方 ISO要么来自自己同步的仓库安全风险主要不在传输环节而在包本身的管理流程。只要做好包的上传审批关闭 GPG 校验能让整个交付顺畅得多。当然如果你们的合规要求明确必须开启那就用同一个私钥给所有包签名别混着来。3. 实操三种离线 yum 源搭建步骤详解3.1 方案 AISO 挂载本地源最快拿下第一台机器这个方法适合应急或者只有一两台机器需要装环境。核心就是把安装光盘 ISO 当作仓库。第一步上传 ISO 到服务器某个目录比如/opt/iso/CentOS-7-x86_64-Minimal-2009.iso。第二步创建挂载点并挂载mkdir -p /mnt/cdrom mount -o loop /opt/iso/CentOS-7-x86_64-Minimal-2009.iso /mnt/cdromCentOS 7 的 ISO 挂载后可以看到repodata目录这就是我们需要的仓库元数据。但 CentOS 8 及以后ISO 结构变了仓库被拆成了BaseOS和AppStream两个子目录需要分别配置两个 repo[BaseOS] nameCentOS-$releasever - BaseOS baseurlfile:///mnt/cdrom/BaseOS enabled1 gpgcheck0 [AppStream] nameCentOS-$releasever - AppStream baseurlfile:///mnt/cdrom/AppStream enabled1 gpgcheck0第三步清理并重建缓存yum clean all yum makecache第四步测试yum install -y vim我之前就犯过一个错CentOS 7 的 ISO 挂载后只配了一个[base]就完事但 CentOS 8 的 ISO 这么配直接提示找不到仓库因为目录结构不一样。所以先ls /mnt/cdrom看一眼目录结构再写 repo永远比盲目照着网上教程抄靠谱。挂载的注意点还有一个mount -o loop只是临时挂载重启后就没了。如果想让机器开机自动挂载建议写进/etc/fstab/opt/iso/CentOS-7-x86_64-Minimal-2009.iso /mnt/cdrom iso9660 loop,defaults 0 03.2 方案 Breposync 同步远程仓库解决大规模内网机器需求如果是几十上百台机器ISO 那点包根本不够看。正确的姿势是准备一台同步机这台机器能访问外网它在本地拉取完整仓库然后通过 HTTP 服务共享给内网。同步机的环境可以是 CentOS 7/8/9或者 Rocky Linux 都行我习惯用和客户端一致的发行版来同步避免版本差异带来兼容性问题。首先安装工具yum install -y createrepo yum-utils然后创建仓库根目录比如/data/yum。接着用reposync同步官方源reposync -r base -p /data/yum --download-metadata reposync -r extras -p /data/yum --download-metadata reposync -r updates -p /data/yum --download-metadata这里每同步一个仓库就会在/data/yum下生成对应的目录比如/data/yum/base。--download-metadata会顺便把远端仓库的元数据拉下来。但有时候元数据下载不完整所以稳妥起见同步完以后统一再生成一次元数据for repo_dir in /data/yum/*/; do createrepo --update $repo_dir done--update参数表示增量生成元数据不会重建整个索引效率高很多。同步完以后把/data/yum目录通过 Nginx 共享出去yum install -y nginxNginx 配置里加一个 locationserver { listen 80; server_name repo.local; location / { root /data/yum; autoindex on; autoindex_exact_size off; } }然后启动 Nginx。这样客户端就能通过http://repo.local/base访问仓库了。我强烈建议用 HTTP 而不是直接用 NFS 或 Samba原因有二一是 HTTP 的权限模型最简单不会出现客户端挂载了共享目录但写不了文件的权限问题二是 HTTP 自带缓存和断点续传语义对 yum 这种大量小文件读取的场景更友好。3.3 方案 Ccreaterepo 自建私有仓库管理散装 rpm 包有时候我们手里只有一堆离线 rpm 包可能是从别的机器上导出过来的也可能是一些商业软件自带的安装包。这时候就需要用createrepo把这些散装 rpm 变成一个真正的仓库。操作很简单mkdir -p /data/private-repo cp *.rpm /data/private-repo/ createrepo /data/private-repo执行完以后/data/private-repo下会生成repodata目录里面就是仓库的元数据文件。然后写一个 repo 文件指向它[private] namePrivate Repository baseurlfile:///data/private-repo enabled1 gpgcheck0到这里绝大部分教程就结束了。但我在实际中用这个方案踩过一个很大的坑createrepo 只负责索引不负责依赖解析。如果你放进仓库的几个 rpm 之间存在依赖关系它们互相之间的依赖都能解析没问题但一旦某个 rpm 依赖了系统里没有的、仓库里也没有的包yum install就会报No available packages而且--skip-broken之类的参数根本救不了。所以自建私有仓库的关键在于这个仓库要能和系统的 base 源同时使用。也就是说客户端既要保留 ISO 或系统的官方源 repo又要加上私有仓库 repo这样 yum 才能在两个仓库之间做联合依赖解析。我自己通常把私有 repo 的优先级设得比官方仓库低一些避免内部包意外覆盖官方包。3.4 更新与增量维护离线源的日常保养离线源不是配完就一劳永逸的尤其 reposync 方案需要定期更新。我的做法是写一个简单的定时任务#!/bin/bash # /usr/local/bin/update_yum_repo.sh reposbase extras updates epel for r in $repos; do reposync -r $r -p /data/yum --download-metadata createrepo --update /data/yum/$r done systemctl reload nginx然后加到 crontab 里0 2 * * 0 /usr/local/bin/update_yum_repo.sh每周日凌晨两点自动同步。这里有个细节reposync在同步时如果遇到网络抖动有些包可能下载不完整导致仓库里出现损坏的 rpm。我建议在仓库目录下定期跑一次repomanage或者用createrepo --update时注意观察日志发现问题包就删掉重新同步。另外磁盘空间要盯着。CentOS 7 的 base extras updates 全量同步大约需要 30-50 GB再加上 epel 的话可能到 100 GB 以上。建议同步机单独挂一块大容量数据盘不要把仓库放在系统盘上否则容易把根分区撑爆。4. 客户端配置与批量分发实践4.1 客户端 repo 文件怎么写最稳服务端搭好了客户端侧才是真正的最后一公里。默认情况下CentOS 有一个/etc/yum.repos.d/CentOS-Base.repo它指向外网的 mirror。离线环境下这个文件会让 yum 卡很久直到超时报错。所以客户端的第一个操作就是把官方 repo 全部禁用或者改名mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak然后新建一个offline.repo[base] nameOffline Base baseurlhttp://repo.local/base enabled1 gpgcheck0 [extras] nameOffline Extras baseurlhttp://repo.local/extras enabled1 gpgcheck0 [updates] nameOffline Updates baseurlhttp://repo.local/updates enabled1 gpgcheck0如果客户端还需要 epel 源那就在服务端同步完 epel 后客户端再加一段[epel] nameOffline EPEL baseurlhttp://repo.local/epel enabled1 gpgcheck0写好之后yum clean all yum makecachemakecache这步一定要做不然 yum 还在用旧的缓存列表安装时仍然会找外网。4.2 批量推送 repo 文件的脚本思路几十台机器的时候手动改文件太累我习惯写一个简单的循环脚本。客户端开启 SSH 免密登录后直接用 scp 推送for host in $(cat hosts.txt); do scp offline.repo root$host:/etc/yum.repos.d/ ssh root$host mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak 2/dev/null; \ mv /etc/yum.repos.d/CentOS-Base.repo.bak /etc/yum.repos.d/CentOS-Base.repo.bak.old 2/dev/null; \ yum clean all; yum makecache done这个脚本我在实际中用过基本能跑通。需要注意的一点是CentOS 8 默认自带的是CentOS-Base.repo和CentOS-AppStream.repo文件名不同批量操作前最好先ls /etc/yum.repos.d/看一眼别把脚本写死否则会漏掉一些文件。4.3 别忘了/etc/hosts和代理的坑客户端如果通过域名访问源服务器/etc/hosts里要有对应解析。另外很多内网机器从前有外网代理配置在/etc/yum.conf里设置了proxyhttp://xxx:port。这种历史配置我见过太多次了离线环境下 yum 会一直尝试走代理结果连不上内网源白等半天。排查的时候一定要看一眼cat /etc/yum.conf | grep proxy如有残留直接注释掉。这算是我个人经验里最容易被忽略的一环。5. 常见问题与排查技巧实录5.1 典型报错速查表报错信息常见原因解决办法Cannot find a valid baseurl for repo: baserepo 文件路径错误或仓库元数据不存在检查baseurl路径拼写确认repodata/repomd.xml存在[Errno 14] HTTP Error 404服务端目录或 Nginx 配置不对检查服务端仓库目录权限、Nginx root 路径是否正确Public key for xxx.rpm is not installedgpgcheck1但没有导入公钥设gpgcheck0或rpm --import导入公钥Package xxx requires: libfoo.so.1()(64bit)依赖缺失检查是否缺少 epel 源或使用 ISO 完整版而不是 Minimal 版同步No more mirrors to trybaseurl 指向的地址不可达用curl -I测试 baseurl 地址是否能访问Error: Cannot retrieve metalink for repository: epel使用了 mirrorlist 而离线环境无法解析改用 baseurl 直连本地仓库这张表我每次排查问题都会对照覆盖面还挺广的。不过有些问题不是表面上一个报错那么简单比如下面的依赖缺失场景牵扯的就比较多。5.2 依赖缺失的处理技巧离线环境下依赖缺失是最头疼的问题没有之一。在线时yum install会自动拉取所有依赖离线时如果仓库不全缺一个 lib 就装不上。我的处理套路是这样的首先确认缺的依赖属于哪个包yum provides libfoo.so.1如果仓库里本来就有这个包只是名字不叫 libfooyum provides会告诉你。如果提示没有任何包提供这个文件那就说明仓库真的缺这个源。下一步我可以从互联网或者别的同版本机器上把这个 rpm 找回来放到私有仓库里然后执行createrepo --update /data/private-repo再回到客户端yum clean all yum makecache yum install -y xxx # 原命令这个过程说起来简单但实际操作中最烦的是依赖链A 依赖 BB 依赖 CC 又依赖 D。所以在离线场合下我强烈建议用reposync 同步完整仓库而不是只同步常用包否则依赖链一定会断。如果手里确实只有少量 rpm 包可以先用rpm -qpR xxx.rpm查看这个包的完整依赖列表提前评估能不能收全rpm -qpR nginx-1.20.1-1.el7.ngx.x86_64.rpm输出里会列出所有依赖包括库文件级别的依赖。把这些依赖挨个找到并放进仓库才能保证安装一次成功。5.3 几个值得单独说的坑第一个坑是makecache 和 clean all 的时机。服务端更新了仓库元数据后客户端不执行yum clean all就跑去安装依然会按本地缓存的老元数据来解析导致明明仓库里有新包客户端却说找不到。这个我踩过不止一次每次都要记得改完 repo / 更新完仓库后客户端先 clean 再 makecache。第二个坑是不同 CentOS 版本的仓库混用。有人图省事把 CentOS 7 的仓库目录直接拿给 CentOS 8 的机器用结果一堆Protected multilib versions或者依赖解析错误。yum 源严格来说要匹配操作系统大版本7 的包不能给 8 用8 的不能给 7 用。如果内网同时存在两个大版本建议建两个独立目录比如/data/yum/7和/data/yum/8各配各的 repo。第三个坑是磁盘 inode 耗尽。rpm 包里都是小文件同步几十万个文件后磁盘空间可能还有剩余但 inode 先用完了。用df -i看一眼如果/data分区 inode 使用率到了 100%哪怕df -h显示空间充足reposync 也会报 No space left on device。这个问题不常见但出现过一次处理方式是给仓库单独挂一个 xfs 或 ext4 分区并且预留 inode 的余量。5.4 关于维护心态的一点建议离线 yum 源这个东西不是一个配一次就永久生效的任务而是一个需要持续维护的基础设施。我见过很多同事配好源之后就不管了等到半年后要装新软件时发现仓库版本太老、依赖缺失一大堆才跑来找我救火。我的建议是把源服务器的同步任务做成定时脚本把仓库更新的日志输出到文件定期看一眼有没有同步失败。另外每次变更仓库内容之后手动在客户端验证一次安装别相信应该没问题实测下来才是最稳的。如果内网规模再大一点、需要的仓库再复杂一点还可以考虑用更高阶的方案来做版本管理比如 Nginx 后面加一层文件同步、多台源服务器做负载均衡或者用更轻量的nginx加rsync做多节点分发。但那些都是后话先把基础的离线源跑稳再研究优化方向也不迟。我在实际运维过程中最深的体会是离线源这个事儿配起来不难难的是把每一步的原理和依赖关系都吃透。路径、权限、元数据、缓存、GPG 校验任何一个环节出了偏差表现出来的问题都很像源坏了但实际上只是一个小配置项的问题。把上面这些笔记从头到尾过一遍你再去面对内网的安装需求基本就能做到一次配好、按需排错了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询