装完 RHEL8,第一件事永远是配源。如果你手头没有红帽订阅,直接yum install的时候大概率会碰一鼻子灰,终端上飘一行红字:This system is not registered with an entitlement server. You can use subscription-manager to register.这时候你再怎么换安装源,只要系统还挂在官方redhat.repo上,结果都是一样的。RHEL8 的源配置,跟以前 CentOS 8 那种改个baseurl就完事的玩法不太一样,它牵涉到订阅机制、仓库结构、镜像站点选型,甚至离线环境下的自建仓库。这篇文章想把这条路完整捋一遍:在线环境怎么用国内镜像,离线环境怎么挂本地源或者自建内网仓库,以及遇到各种报错怎么排查。适合刚从 CentOS 7/8 切到 RHEL8 的运维,也适合机房没有外网、需要自建 yum 源的人参考。
1. RHEL8 仓库机制与配源前的认知准备
1.1 RHEL8 默认仓库结构:BaseOS 与 AppStream
很多人第一次配 RHEL8 源的时候,习惯性去找base、extras、updates这三个仓库,结果发现 RHEL8 的套路完全不一样。RHEL8 把原本的发行版仓库重新划分成了两个核心仓:BaseOS和AppStream。
BaseOS装的是底层系统组件,比如 kernel、glibc、systemd 这类“地基”性质的包。AppStream则是一个特别的设计,它支持模块化(module)概念,同一个软件可以存在多个版本流。最典型的例子是 nginx,你可以通过dnf module在 1.14、1.18、1.20 这些版本流之间做选择。用生活化一点的比喻:BaseOS相当于毛坯房的地基和承重墙,AppStream则是装修套餐,你可以按需选不同风格。理解了这一层,后面配源的时候就不会对着仓库名字发懵。
仓库文件的默认位置在/etc/yum.repos.d/,配置文件是/etc/dnf/dnf.conf。RHEL8 的dnf和yum命令其实是一个东西,yum是指向dnf的软链接,所以你在 RHEL8 上敲yum repolist跟敲dnf repolist实际走的是同一套逻辑。
1.2 为什么 RHEL8 要“换源”或者“配源”
RHEL8 的官方仓库由subscription-manager管理,它读的是/etc/yum.repos.d/redhat.repo。没有红帽订阅或者没有注册红帽账号的话,redhat.repo里的仓库根本没法用,dnf会把请求转发到红帽订阅服务器,然后返回一个 entitlement 错误。
国内镜像站其实没有公开同步 RHEL 官方仓库,因为 RHEL 的二进制软件包版权要求比 CentOS 严格,镜像站只能同步 CentOS、Rocky、AlmaLinux 这些开源发行版。所以网上常说的“RHEL8 配置国内源”,在实操层面往往有三种走法:第一种,买或者申请红帽开发者订阅,走官方源,这是最稳的;第二种,把仓库指向跟 RHEL8 兼容的 Rocky Linux 或者 AlmaLinux 镜像,本质是借用开源替代发行版的二进制包,适合个人学习测试和内部环境;第三种,只追加 EPEL 这类补充仓库,用来装htop、jq、screen等常用软件。
我个人给的建议是这样的:有条件的生产环境,优先考虑官方订阅;如果没有订阅,又想少踩坑,Rocky Linux 的镜像源是替代方案里兼容性最好的一个。下文以这个思路为主讲操作。
1.3 动手前的检查清单
在写任何 repo 文件之前,先花一分钟确认三件事,能帮你省掉后面一大半的排查时间。
第一,确认系统版本和架构。跑一遍:
cat /etc/os-release uname -mos-release会告诉你当前是 RHEL8 还是 Rocky、Alma 之类重建版,uname -m决定你用x86_64还是aarch64的仓库路径。不同架构的软件包路径前缀不一样,镜像站上aarch64目录和x86_64目录是分开的。
第二,看看现在/etc/yum.repos.d/里到底有什么。有的系统装完会自动生成一堆.repo文件,残留的仓库引用会让dnf在 makecache 的时候报各种奇怪的错。操作前先备份整个目录,这是老规矩:
mkdir -p /etc/yum.repos.d/backup cp -r /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/第三,测一下到镜像站的网络连通性。curl -I能快速判断目标站点通不通,省得配完才发现根本不是源的问题,而是内网防火墙把出网流量拦了:
curl -I https://mirrors.aliyun.com2. 配置国内镜像源(在线可用)
2.1 国内镜像站怎么选:横向对比
国内能用的镜像站不少,阿里云、清华 TUNA、中科大 USTC、华为云都有稳定的同步服务。镜像站本身不求多,选一个主力、一个备用就够了。下面是我实际对比下来的感受:
| 镜像站 | 仓库路径 | 同步速度 | 优势 |
|---|---|---|---|
| 阿里云 | mirrors.aliyun.com/rockylinux | 快,大厂带宽稳定 | 国内大部分云服务器访问延迟低,遇到大版本同步极少落后 |
| 清华 TUNA | mirrors.tuna.tsinghua.edu.cn/rockylinux | 快,教育网体验极佳 | 同步策略很规范,目录结构清晰,离线源 rsync 常用它 |
| 中科大 USTC | mirrors.ustc.edu.cn/rockylinux | 快 | 带宽稳定,部分时间段速度媲美阿里 |
| 华为云 | mirrors.huaweicloud.com/rockylinux | 快 | 云上服务器友好,路径和阿里类似 |
选择原则很简单:你的云服务器在哪个厂商那里,优先用哪家的镜像,网络链路最短,速度最稳。如果是在普通机房,阿里云和清华基本不会让你失望。
2.2 阿里云源配置步骤(以 Rocky 索引路径为例)
前面说过,RHEL8 没有公开的官方红帽镜像,所以我这里用 Rocky Linux 8 的镜像路径来为 RHEL8 提供第三方兼容仓库。先用编辑器新建一个 repo 文件,我习惯命名为aliyun-rocky.repo:
[BaseOS] name=BaseOS baseurl=https://mirrors.aliyun.com/rockylinux/8/BaseOS/$basearch/os/ gpgcheck=0 enabled=1 [AppStream] name=AppStream baseurl=https://mirrors.aliyun.com/rockylinux/8/AppStream/$basearch/os/ gpgcheck=0 enabled=1 [extras] name=extras baseurl=https://mirrors.aliyun.com/rockylinux/8/extras/$basearch/os/ gpgcheck=0 enabled=1这里有个细节要解释。$basearch是 dnf 自带的变量,执行时自动替换为x86_64或aarch64。gpgcheck=0是为了跳过 GPG 签名验证写上的,因为当前系统没有 Rocky Linux 官方的 RPM-GPG-KEY,不关掉的话dnf install会报公钥找不到的错。如果你比较在意安全校验,可以先在系统里导入 Rocky 的官方公钥,再把gpgcheck改为 1:
rpm --import https://mirrors.aliyun.com/rockylinux/8/RPM-GPG-KEY-rockyofficial写完 repo 文件后,先把原来的官方订阅仓库临时移开,避免 makecache 阶段又去连红帽的订阅服务器。注意不要删,移到 backup 目录就行。然后清理缓存并重建:
dnf clean all dnf makecachemakecache跑完如果没有任何报错,说明源已经通了。此时再执行dnf repolist,应该能看到三个 enabled 状态的仓库。
2.3 清华 / 中科大镜像源替换
如果阿里云源在你的网络环境下速度不理想,或者是教育网内的机器,换成清华 TUNA 也就是改一个 URL 的事。把上面的baseurl全部替换成:
baseurl=https://mirrors.tuna.tsinghua.edu.cn/rockylinux/8/BaseOS/$basearch/os/ baseurl=https://mirrors.tuna.tsinghua.edu.cn/rockylinux/8/AppStream/$basearch/os/ baseurl=https://mirrors.tuna.tsinghua.edu.cn/rockylinux/8/extras/$basearch/os/中科大源同理:
baseurl=https://mirrors.ustc.edu.cn/rockylinux/8/BaseOS/$basearch/os/ baseurl=https://mirrors.ustc.edu.cn/rockylinux/8/AppStream/$basearch/os/ baseurl=https://mirrors.ustc.edu.cn/rockylinux/8/extras/$basearch/os/实际操作中我踩过一个小坑:有人会同时把阿里云的 BaseOS 和清华的 BaseOS 放在不同的 repo 文件里,仓库 ID 还都是[BaseOS]。这样dnf会拿后加载的仓库覆盖前一个,结果就是两个源哪边都不生效,或者dnf在两个仓库之间反复横跳。无论你选哪个镜像站,同一个仓库尽量只保留一个定义。
2.4 加装 EPEL 扩展仓库
RHEL8 自带的仓库数量非常克制,装完系统你会发现连htop、jq、ncdu都没有。这时候就需要 EPEL(Extra Packages for Enterprise Linux)。EPEL 是一个针对 RHEL 系发行版维护的扩展软件包仓库,由开源社区维护,包数量远多于 BaseOS 和 AppStream。
我推荐直接手写 EPEL 的 repo 文件,而不是下载epel-release安装包。手写的好处是地址可以直接指向国内镜像,省去epel-release默认从国外 Fedora 站点下载的慢速等待:
[epel] name=EPEL baseurl=https://mirrors.aliyun.com/epel/8/Everything/$basearch/ enabled=1 gpgcheck=0如果你坚持要 GPG 校验,可以导入 EPEL 的公钥再打开校验:
rpm --import https://mirrors.aliyun.com/epel/RPM-GPG-KEY-EPEL-8装完 EPEL 后,记得再执行一次dnf clean all && dnf makecache,让 EPEL 的 metadata 进缓存。
2.5 验证仓库是否可用
配源操作完成后,别急着跑了,先做一轮基础验证:
dnf repolist dnf list --available | wc -lrepolist输出里能看到每个仓库的软件包数量。包数量是零或者只有几个,说明仓库路径有问题。然后再实际装一个小软件测试,比如:
dnf install -y vim jq htopvim来自 BaseOS/AppStream,jq和htop需要 EPEL。三个包都装成功,说明仓库链路和依赖解析都没问题。
3. 本地镜像源搭建:从 ISO 到内网仓库
3.1 本地源使用场景与整体思路
本地源,也叫离线源,最典型的场景是机房内网隔离环境。几十台机器都没有外网,每台机器走一遍外网源根本不现实,尤其当安装的包数量很大的时候。更常见的做法是找一台有外网权限或者能挂载安装 ISO 的服务器,把它变成内网 yum 仓库,其他机器全部指向这台内网地址。
整体思路其实就三步:第一步,准备软件包数据,可以挂载 RHEL8 安装 ISO,也可以用rsync同步镜像站;第二步,提供传输通道,最简单的是用nginx或者python3 -m http.server把仓库目录暴露成 HTTP;第三步,客户端写好本地仓库 repo 文件,执行dnf makecache。
3.2 使用 RHEL8 ISO 挂载做本机源
如果你手里有 RHEL8 的 DVD ISO,这是最省事的做法。ISO 里本身就带好了repodata,不需要额外生成 metadata,直接把 ISO 挂载到目录就能当仓库用:
mkdir -p /mnt/iso mount -o loop /path/to/rhel-8.x-x86_64-dvd.iso /mnt/iso挂载完看一下目录结构:
ls /mnt/iso里面会有BaseOS、AppStream、images、isolinux等目录。接下来写一个本机源的 repo 文件:
[BaseOS-Local] name=BaseOS-Local baseurl=file:///mnt/iso/BaseOS gpgcheck=0 enabled=1 [AppStream-Local] name=AppStream-Local baseurl=file:///mnt/iso/AppStream gpgcheck=0 enabled=1file://开头的 URL 是dnf支持的本地路径格式。写完后执行:
dnf clean all dnf makecache如果 ISO 的仓库定义正常,makecache 会顺利通过。这个方式的局限性也很明显:ISO 里的软件包版本是固定的,系统装完后无法得到更新。所以这种方法只适合安装阶段和基础环境固定不动的机器,如果系统需要持续升级,我建议用下一节的方法。
3.3 使用 HTTP 服务把本地源共享给内网
把 ISO 挂载成本机源只能解决一台机器的问题,内网几十台机器要想都用这个源,就需要一个 HTTP 服务。
最简单的方式,先安装 nginx:
dnf install -y nginx然后改配置/etc/nginx/conf.d/repo.conf,核心是开启autoindex,让客户端能索引目录下的文件:
server { listen 80; server_name _; root /mnt/iso; autoindex on; }启动 nginx 并设置开机自启:
systemctl enable --now nginx如果系统里有 firewalld,记得放行 HTTP 端口:
firewall-cmd --permanent --add-service=http firewall-cmd --reload客户端机器上的 repo 文件可以这么写:
[BaseOS-Local] name=BaseOS-Local baseurl=http://192.168.1.10/BaseOS gpgcheck=0 enabled=1 [AppStream-Local] name=AppStream-Local baseurl=http://192.168.1.10/AppStream gpgcheck=0 enabled=1192.168.1.10是仓库服务器的内网 IP,实际使用时替换成你自己的地址。为了便于维护,我通常会用软件配置管理工具把这份 repo 文件推送到所有客户端,避免一台台手工敲。
3.4 同步镜像站构建完整离线源(rsync + createrepo)
ISO 自带的软件包数量有限,如果内网机器需要安装的软件五花八门,更彻底的办法是同步一个完整的仓库到本地硬盘。这里以同步 Rocky Linux 8 的 BaseOS 和 AppStream 为例,用rsync从清华镜像站拉取:
dnf install -y rsync mkdir -p /data/repo/rockylinux/8 rsync -avz --delete rsync://mirrors.tuna.tsinghua.edu.cn/rockylinux/8/ /data/repo/rockylinux/8/这个命令看参数就能明白大概意思:-a归档模式保留权限和时间戳,-z压缩传输,--delete保持本地和远端严格一致。同步量级视网络情况而定,BaseOS、AppStream 加起来大约 8 到 10 GB,建议磁盘至少预留 20 GB 空间。
同步完成后,一般来说目录里已经带上了官方的repodata。如果因为某些情况 repodata 缺失或者你需要更新索引,用createrepo_c重新生成:
dnf install -y createrepo_c createrepo_c --update /data/repo/rockylinux/8/BaseOS createrepo_c --update /data/repo/rockylinux/8/AppStream--update参数表示在已有 repodata 基础上增量更新,比全量生成快得多。后面如果做了定时同步,每次同步完跑一遍就能保持内网仓库的索引最新。这个流程搭建完成后,再结合上一节的 nginx 配置,把 root 指向/data/repo,内网机器就拥有一个可持续更新的低频离线源了。
4. 常见问题与排查技巧实录
4.1 未订阅注册导致的 entitlement 报错
如果你在配源之前就执行过dnf install,大概率见过这条经典报错:
This system is not registered with an entitlement server. You can use subscription-manager to register.出现这个错误的原因不是仓库地址写错,而是系统默认在/etc/yum.repos.d/redhat.repo里配置了红帽订阅源。解决方式取决于你的路线。走官方订阅路线,执行:
subscription-manager register --username 你的红帽账号 --password 你的密码 subscription-manager refresh subscription-manager attach --auto走第三方兼容源路线,把redhat.repo暂时移出仓库目录,然后按照本文第二章节的内容配置替代源:
mv /etc/yum.repos.d/redhat.repo /etc/yum.repos.d/backup/我自己的经验是:这个动作只影响仓库列表,不涉及系统内核和系统文件,风险很小,所以测试环境里可以放心操作。
4.2 repomd.xml 下载失败 / 404 错误
dnf makecache时最常见的一类报错是:
http://xxx/repodata/repomd.xml: [Errno 14] HTTP Error 404 - Not Found遇到repomd.xml报错,十有八九是仓库 URL 路径不对。排查方向有几个:第一,检查镜像站实际目录结构。你可以直接用curl或者浏览器打开baseurl的上一级目录,确认路径里面到底有没有BaseOS/$basearch/os/这个层级。第二,检查$basearch和$releasever变量的实际值。如果你在配置里写了$releasever,RHEL8 可能解析成8或8.9,不同版本解析结果不一样,镜像站有没有这个版本目录也未知。最省事的办法是在baseurl里硬编码大版本号,比如/rockylinux/8/BaseOS/x86_64/os/,虽然少了一点灵活性,但排错成本最低。
4.3 GPG 密钥校验与 gpgcheck 处理
第三方源最容易踩的坑就是gpgcheck=1但系统没有对应公钥。报错信息大概是:
The GPG keys listed for the "BaseOS" repository are already installed but they are not correct for this package.这里要理清一个观念:gpgcheck=1本身没有错,错在当前仓库引用的公钥跟软件包签名不匹配。RHEL8 官方源用的公钥是红帽的,而 Rocky 源的包是用 Rocky 官方公钥签名的,混用自然过不了校验。解决办法有两个:一是按第 2.2 节里的方法,先导入对应发行版的官方公钥,再把gpgcheck保持为 1;二是在测试环境图省事,直接把所有自定义源的gpgcheck设为 0。我个人建议:生产环境尽量导入公钥,不要把签名校验一刀切关掉,否则一旦镜像源被劫持,你装进去的可能是一堆来路不明的二进制包。
4.4 dnf 模块化与应用流导致的安装失败
RHEL8 的AppStream仓库引入了模块化概念,这导致有些软件的直接安装命令会微微不同。比如你执行dnf install nginx没问题,但如果你想安装特定版本的 PHP 或者 Node.js,可能要先启用对应的模块流:
dnf module list php dnf module enable php:7.4 dnf install php如果你没启用模块,又恰好仓库里没有匹配的版本流,dnf会报类似Unable to match profile或者No available modular packages的错误。这个错跟源配置本身关系不大,但初次接触 RHEL8 的人很容易误判为源失效。排查的时候先看报错里有没有module关键字,有的话先处理模块流,比反复换源有效得多。
4.5 缓存、并发锁与源优先级问题
日常使用中我发现一个规律:大部分dnf起不来的问题,第一步永远是dnf clean all。缓存目录/var/cache/dnf里如果残留了上一份仓库的 metadata,换源之后对不上就会产生各种诡异报错。清掉缓存重新 makecache,能解决七成问题。
第二个常见问题是多个同名仓库冲突。如果你一开始配了阿里云源,后来又换了清华源,但[AppStream]这个仓库 ID 两次都在用,dnf 加载时会发生覆盖或随机选择,装包就时好时坏。排查以后把不用的 repo 文件移出目录,只保留一套有效定义,再看是否复现。如果你确实需要从多个源安装软件,建议用dnf config-manager --set-disabled把暂时不用的源先禁用掉:
dnf install -y dnf-plugins-core dnf config-manager --set-disabled epel如果你真的需要精细控制源优先级,可以额外装dnf-plugin-priorities插件。不过我的经验是,优先级配置越复杂,后面排查越麻烦,能少用就少用。
5. 写在后面:三条过来人建议
讲完了配置步骤和排错思路,最后分享几个我自己实际踩坑之后的习惯。
第一个习惯,改仓库配置之前永远先备份。cp -r /etc/yum.repos.d真的就是一条命令的事,但能让你在配错一个 URL 之后不用手工去回忆原来的仓库文件长什么样。
第二个习惯,一个系统里尽量只信任一个主力源,辅助源最多再加一个 EPEL。仓库文件越少越干净,交叉依赖和源冲突的概率直线下降。
第三个习惯,如果内网机器数量超过十台,别让它们各自去访问外网源。搭一台内网仓库服务器,用rsync定时同步一次,或者直接挂载 ISO 做 HTTP 分享,后续维护成本会低很多。
RHEL8 的源配置本质上不是技术难度高的问题,而是需要你理解发行版的仓库设计逻辑,再做合适的路径选择。把这套思路理顺了,无论是切换到 Rocky、Alma 还是以后升级到 RHEL9,底层都是同一套玩法,只是路径名和版本号变了而已。