<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>vict0ri4</title><description>Linux · 网络 · 容器化部署笔记</description><link>https://cyclicspace.site/</link><language>en</language><item><title>解决 Gentoo 中 Corectrl 编译报错问题</title><link>https://cyclicspace.site/posts/corectrl/</link><guid isPermaLink="true">https://cyclicspace.site/posts/corectrl/</guid><description>解决因 dev-libs/quazip 移除 qt6 USE 标记导致 corectrl 无法编译的问题</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ 状态说明（2026-10）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本文记录的是 2026 年 8 月 Gentoo 下 CoreCtrl 1.5.2 的一个特定编译错误。Gentoo overlay 可能已在后续版本（如 &lt;code&gt;1.5.2-r2&lt;/code&gt;）中修复了该依赖问题，请优先尝试直接安装。&lt;/p&gt;
&lt;p&gt;此外，CoreCtrl 项目已进入维护模式，不再添加新功能或硬件支持；如需活跃开发的 GPU 控制工具，可考虑 &lt;strong&gt;LACT&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;gentoo-solution-corectrl&lt;/h1&gt;
&lt;h2&gt;介绍&lt;/h2&gt;
&lt;p&gt;由于dev-libs/quazip-1.5版本中直接移除了qt5和qt6两个带有Qt版本选择的 USE 标记，导致在gentoo中编译kde-misc/corectrl-1.5.2时提示以下信息：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;emerge: there are no ebuilds built with USE flags to satisfy &quot;dev-libs/quazip[qt6]&quot;.
!!! One of the following packages is required to complete your request:
- dev-libs/quazip-1.5::gentoo (Missing IUSE: qt6)
(dependency required by &quot;kde-misc/corectrl-1.5.2::farmboy0&quot; [ebuild])
(dependency required by &quot;kde-misc/corectrl&quot; [argument])
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个错误是因为 corectrl 的 ebuild 中写死了需要 dev-libs/quazip[qt6]（即安装了 qt6 USE 标志的 quazip），但新版的 quazip 已经默认且仅支持 Qt6，因此移除了 qt6 这个 USE 标志，导致 Portage 在依赖树中找不到满足条件的包。&lt;/p&gt;
&lt;h2&gt;解决方案&lt;/h2&gt;
&lt;h3&gt;找到 corectrl 的 ebuild 文件&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;find /var/db/repos -name &quot;corectrl-1.5.2.ebuild&quot; 2&amp;gt;/dev/null&lt;/code&gt;
不出意外的话，路径会是 /var/db/repos/farmboy0/kde-misc/corectrl/corectrl-1.5.2.ebuild。&lt;/p&gt;
&lt;h3&gt;编辑 ebuild 文件&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sudo vi /var/db/repos/farmboy0/kde-misc/corectrl/corectrl-1.5.2.ebuild&lt;/code&gt;
找到包含 dev-libs/quazip[qt6] 的那一行（通常在 RDEPEND 或 DEPEND 变量里），改为dev-libs/quazip[qt6(+)]&lt;/p&gt;
&lt;h3&gt;重新生成 Manifest 文件&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;cd /var/db/repos/farmboy0/kde-misc/corectrl/&lt;/code&gt;
&lt;code&gt;sudo ebuild corectrl-1.5.2.ebuild manifest&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;安装&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sudo emerge -av kde-misc/corectrl&lt;/code&gt;&lt;/p&gt;
</content:encoded></item><item><title>在 Linux 下用 USB 网卡开 WiFi 热点</title><link>https://cyclicspace.site/posts/gentoo_hotspot/</link><guid isPermaLink="true">https://cyclicspace.site/posts/gentoo_hotspot/</guid><description>把 USB 无线网卡做成手机能连的 AP，并做成开机自启服务</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;在 Linux 下用 USB 网卡开 WiFi 热点&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;主机：Gentoo Linux（OpenRC）
日期：2026-10-18&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;前言&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;此文章用于记录我自己在一台 Gentoo 机器上用 USB 无线网卡开热点的过程。&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;免责声明&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本文介绍的是&lt;strong&gt;通用 WiFi 热点（AP）搭建技术&lt;/strong&gt;，仅适用于&lt;strong&gt;完全可控的网络环境&lt;/strong&gt;，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;家庭独立宽带&lt;/li&gt;
&lt;li&gt;实验室或工作场所分配的独立网络&lt;/li&gt;
&lt;li&gt;自己的流量卡&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;严禁在以下环境使用&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;校园网&lt;/li&gt;
&lt;li&gt;公司内网&lt;/li&gt;
&lt;li&gt;公共 WiFi&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;请遵守所在网络的用户协议，任何滥用行为与本文作者无关。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;先理解数据流向&lt;/h2&gt;
&lt;p&gt;手机连上 &lt;code&gt;wlan0&lt;/code&gt;，dnsmasq 给它发一个 &lt;code&gt;192.168.42.x&lt;/code&gt; 的地址。之后它的上网流量到达本机，内核转发（&lt;code&gt;net.ipv4.ip_forward=1&lt;/code&gt;），再做一次源地址转换（masquerade），最后从 &lt;code&gt;enp37s0&lt;/code&gt; 出去。&lt;/p&gt;
&lt;p&gt;整条链路上有四件事要做。hostapd 管无线信号和认证，dnsmasq 只管发 IP，NAT 管地址转换，sysctl 管打开转发。&lt;/p&gt;
&lt;p&gt;其中 NAT 是绕不过去的：&lt;code&gt;192.168.42.0/24&lt;/code&gt; 是私网网段，上游路由器不认识它，回程流量回不来就上不了网。区别只在于用什么工具做（nftables、iptables、firewalld、ufw 都行，见下文）。防火墙过滤则是可选的，本来就有防火墙的机器才需要额外放行。&lt;/p&gt;
&lt;h2&gt;前提&lt;/h2&gt;
&lt;p&gt;先确认两张网卡的名字。下面以 &lt;code&gt;wlan0&lt;/code&gt; 和 &lt;code&gt;enp37s0&lt;/code&gt; 为例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip -br link | grep -i wl     # 无线网卡，做热点的那个
ip -br link | grep -i en     # 有线网卡，接上游的那个
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;无线网卡需要支持 AP 模式（&lt;code&gt;nl80211&lt;/code&gt;）。USB 网卡里 mt7921u、rtl8812au 这些通常都支持。不支持的话，hostapd 启动时会报 &lt;code&gt;nl80211: Failed to set interface wlan0 into AP mode&lt;/code&gt; 这样的错误。&lt;/p&gt;
&lt;p&gt;拿不准的话，装好 &lt;code&gt;iw&lt;/code&gt;（见下节）后可以用 &lt;code&gt;iw list&lt;/code&gt; 查：&lt;code&gt;Supported interface modes&lt;/code&gt; 下列出 &lt;code&gt;* AP&lt;/code&gt; 就说明支持。&lt;/p&gt;
&lt;h2&gt;依赖包&lt;/h2&gt;
&lt;p&gt;要搭建这样一个热点需要安装 &lt;code&gt;hostapd&lt;/code&gt;、&lt;code&gt;dnsmasq&lt;/code&gt;、&lt;code&gt;wireless-regdb&lt;/code&gt;、&lt;code&gt;iw&lt;/code&gt; 四个软件包。&lt;code&gt;wireless-regdb&lt;/code&gt; 提供各国的无线监管域数据，hostapd 里的 &lt;code&gt;country_code=CN&lt;/code&gt; 要用到它；&lt;code&gt;iw&lt;/code&gt; 用来确认网卡是否支持 AP 模式。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo emerge -av hostapd dnsmasq wireless-regdb iw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;另外还需要一个做 NAT 的工具。如果你的系统本来就有防火墙（nftables / iptables / firewalld / ufw），直接用它就行，不用额外装；如果什么防火墙都没有，那就装一个，本文以 nftables 为例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo emerge -av nftables
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;别的发行版包名基本也差不多，只需把安装软件的命令替换成对应发行版的即可。&lt;/p&gt;
&lt;h2&gt;搭建&lt;/h2&gt;
&lt;h3&gt;hostapd&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/hostapd/hostapd_2g.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;interface=wlan0
driver=nl80211
ssid=MyHotspot
hw_mode=g
channel=6
ieee80211n=1
wmm_enabled=1

# 监管域
country_code=CN
ieee80211d=1

auth_algs=1
wpa=2
wpa_passphrase=&amp;lt;你的密码&amp;gt;
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
rsn_pairwise=CCMP
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;记得把上面配置里的 &quot;&amp;lt;你的密码&amp;gt;&quot; 替换成你实际想设置的 WiFi 密码。&lt;/p&gt;
&lt;h3&gt;dnsmasq&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/dnsmasq.d/hotspot.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;interface=wlan0
bind-interfaces

# 网段需要与下面 NAT 规则里的网段一致
dhcp-range=192.168.42.100,192.168.42.200,12h

dhcp-option=3,192.168.42.1 # 本机默认网关
dhcp-option=6,223.5.5.5 # 公共 DNS，客户端不经过本机

# 记录每次 DHCP 交互，排查 &quot;连上但分配不到 IP&quot; 时很有用，不需要时也可以注释掉
log-dhcp
log-facility=/var/log/dnsmasq-hotspot.log
log-async=25
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;内核转发&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/sysctl.d/99-hotspot.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;# 客户端要能出网，必须打开 IPv4 转发
net.ipv4.ip_forward = 1

# 我完全不转发 IPv6，有需要可以自行开启
net.ipv6.conf.all.forwarding = 0

# 接上游的有线口不接收 RA
net.ipv6.conf.enp37s0.accept_ra = 0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;sudo sysctl -p /etc/sysctl.d/99-hotspot.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;放入 &lt;code&gt;/etc/sysctl.d/&lt;/code&gt; 是为了让内核参数单独有个文件管，和 NAT / 防火墙规则分开。&lt;/p&gt;
&lt;h3&gt;NAT&lt;/h3&gt;
&lt;p&gt;客户端用的是私网地址，上游不认识，必须在本机出口上把源地址换成 &lt;code&gt;enp37s0&lt;/code&gt; 的地址。&lt;/p&gt;
&lt;p&gt;下面列出几种做法，挑一种即可：&lt;/p&gt;
&lt;p&gt;nftables（&lt;code&gt;net-firewall/nftables&lt;/code&gt; 不提供 &lt;code&gt;/etc/nftables.conf&lt;/code&gt;，需要自己建。&lt;strong&gt;如果这个文件已经存在，则只在末尾追加下面这段，不要整体替换&lt;/strong&gt;，因为你可能已经有一整套防火墙规则在里面）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/nftables.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/nft -f

define WAN    = &quot;enp37s0&quot;
define LANNET = 192.168.42.0/24

destroy table ip hotspot_nat

table ip hotspot_nat {
	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		oifname $WAN ip saddr $LANNET masquerade
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;sudo nft -f /etc/nftables.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;追加到已有文件时注意两点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;首行的 &lt;code&gt;#!/usr/bin/nft -f&lt;/code&gt; 只在新建文件时需要，追加时不要带上。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;define&lt;/code&gt; 必须在使用之前出现。两行 &lt;code&gt;define&lt;/code&gt; 放进文件靠前的 &lt;code&gt;define&lt;/code&gt; 区，&lt;code&gt;destroy table ip hotspot_nat&lt;/code&gt; 和 &lt;code&gt;table ip hotspot_nat {...}&lt;/code&gt; 放到文件末尾。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;整段贴在末尾会让 &lt;code&gt;define&lt;/code&gt; 出现在使用之后，nft 会直接报错。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;LANNET&lt;/code&gt; 必须和上面 dnsmasq 的 &lt;code&gt;dhcp-range&lt;/code&gt; 对得上，否则 masquerade 匹配不到。&lt;/p&gt;
&lt;p&gt;iptables（很多系统还在用）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo iptables -t nat -A POSTROUTING -s 192.168.42.0/24 -o enp37s0 -j MASQUERADE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;先用 &lt;code&gt;sudo iptables -S FORWARD | head -1&lt;/code&gt; 看一眼策略，如果是 &lt;code&gt;DROP&lt;/code&gt;，还得放行转发，否则客户端照样上不了网：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo iptables -A FORWARD -i wlan0 -o enp37s0 -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;FORWARD&lt;/code&gt; 默认是 &lt;code&gt;ACCEPT&lt;/code&gt; 的机器不用加这两条。&lt;/p&gt;
&lt;p&gt;firewalld 和 ufw 都要改&quot;默认转发策略 + masquerade&quot;，但改的位置完全不同：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;firewalld&lt;/strong&gt;：把 &lt;code&gt;enp37s0&lt;/code&gt; 划进 &lt;code&gt;external&lt;/code&gt; 区并打开 masquerade，两条都带 &lt;code&gt;--permanent&lt;/code&gt;：&lt;code&gt;firewall-cmd --zone=external --change-interface=enp37s0 --permanent&lt;/code&gt;、&lt;code&gt;firewall-cmd --zone=external --add-masquerade --permanent&lt;/code&gt;，最后 &lt;code&gt;firewall-cmd --reload&lt;/code&gt; 生效。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ufw&lt;/strong&gt;：没有 zone 这个概念，要在 &lt;code&gt;/etc/ufw/before.rules&lt;/code&gt; &lt;strong&gt;最前面&lt;/strong&gt;加一段 nat 规则，再把 &lt;code&gt;/etc/default/ufw&lt;/code&gt; 里的 &lt;code&gt;DEFAULT_FORWARD_POLICY&lt;/code&gt; 改成 &lt;code&gt;ACCEPT&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 192.168.42.0/24 -o enp37s0 -j MASQUERADE
COMMIT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;改完 &lt;code&gt;sudo ufw reload&lt;/code&gt; 生效。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NAT 规则怎么开机生效，取决于你用的工具，各发行版一般都有现成方案。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;nftables&lt;/strong&gt;：用 Gentoo 自带的 &lt;code&gt;net-firewall/nftables&lt;/code&gt; 服务。它是快照模型，适合机器上只维护这一份规则的情况，按顺序执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nft -f /etc/nftables.conf
sudo rc-service nftables save
sudo rc-update add nftables default
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个服务启动时会检查 &lt;code&gt;/var/lib/nftables/rules-save&lt;/code&gt;，文件不存在就直接拒绝启动。&lt;code&gt;rc-update&lt;/code&gt; 只是加开机链接、不启动服务，所以 &lt;code&gt;save&lt;/code&gt; 真正要赶在下次重启之前跑过。&lt;/p&gt;
&lt;p&gt;快照的含义是：&lt;code&gt;/etc/nftables.conf&lt;/code&gt; 只在 &lt;code&gt;nft -f&lt;/code&gt; 时读一次，&lt;code&gt;save&lt;/code&gt; 把当时内核里的整份规则写进 &lt;code&gt;rules-save&lt;/code&gt;，开机加载的是它。所以每次改完规则，除了 &lt;code&gt;nft -f&lt;/code&gt;，还要再 &lt;code&gt;rc-service nftables save&lt;/code&gt; 一次，否则重启会回退到上一次快照。&lt;/p&gt;
&lt;p&gt;正因为快照会把内核里&lt;strong&gt;所有&lt;/strong&gt;表一起写进去，而服务加载前又会 &lt;code&gt;flush ruleset&lt;/code&gt;，所以机器上要是有 tailscale、libvirt 这类自己建表的软件，就别用这个服务，改用 &lt;a href=&quot;/posts/nftables-firewall-setup/&quot;&gt;接管服务的做法&lt;/a&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;iptables&lt;/strong&gt;：&lt;code&gt;sudo rc-service iptables save&lt;/code&gt; + &lt;code&gt;sudo rc-update add iptables default&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;firewalld&lt;/strong&gt;：本身就是常驻服务，&lt;code&gt;--permanent&lt;/code&gt; 的改动自动持久，不用额外操作。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;防火墙过滤（可选）&lt;/h3&gt;
&lt;p&gt;如果机器没有配置防火墙，或者防火墙默认放行，等下面 &lt;code&gt;hotspot&lt;/code&gt; 服务跑起来热点就能用了，这节可以跳过。&lt;/p&gt;
&lt;p&gt;如果机器上有 &lt;code&gt;policy drop&lt;/code&gt; 这类默认拒绝的防火墙，需要额外放行这几样：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wlan0&lt;/code&gt; 上的 DHCP（udp/67）：不给 dnsmasq 放行，客户端连上了也拿不到 IP&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wlan0&lt;/code&gt; → &lt;code&gt;enp37s0&lt;/code&gt; 的转发&lt;/li&gt;
&lt;li&gt;转发链里的 &lt;code&gt;ct state established,related accept&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;（如果把 dnsmasq 改成下发本机地址 &lt;code&gt;dhcp-option=6,192.168.42.1&lt;/code&gt;，让客户端走本机 DNS，那还要再加一条 udp/53 的放行。本文下发的是 &lt;code&gt;223.5.5.5&lt;/code&gt;，客户端不经过本机，所以不用开。）&lt;/p&gt;
&lt;p&gt;最后一条最容易漏：&lt;code&gt;policy drop&lt;/code&gt; 只放行&quot;客户端 → 上游&quot;这一个方向，服务器回来的包方向是反的，匹配不到任何规则，全靠 conntrack 放行。少了它客户端能拿到 IP，但什么都连不上——DNS 查询和网页访问一起失败。&lt;/p&gt;
&lt;h3&gt;hotspot&lt;/h3&gt;
&lt;p&gt;新建 &lt;code&gt;/etc/init.d/hotspot&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/sbin/openrc-run
# 职责：配置无线接口 + dnsmasq + hostapd
#   - NAT / 防火墙 -&amp;gt; 由你选定的那套工具负责
#   - ip_forward -&amp;gt; /etc/sysctl.d/99-hotspot.conf （由 sysctl 服务加载）

rc_need=&quot;net&quot;

IFACE=wlan0
GATEWAY=192.168.42.1

DNSMASQ_PID=/run/hotspot_dnsmasq.pid
HOSTAPD_PID=/run/hotspot_hostapd.pid

# 等某个 pidfile 出现、且对应进程还活着
_wait_pidfile() {
	local pf=&quot;$1&quot; timeout=&quot;$2&quot; i=0 pid
	local max=$(( timeout * 10 ))      # 每次 0.1 秒
	while [ &quot;$i&quot; -lt &quot;$max&quot; ]; do
		if [ -r &quot;$pf&quot; ]; then
			pid=&quot;$(cat &quot;$pf&quot; 2&amp;gt;/dev/null)&quot;
			if [ -n &quot;$pid&quot; ] &amp;amp;&amp;amp; kill -0 &quot;$pid&quot; 2&amp;gt;/dev/null; then
				return 0
			fi
		fi
		sleep 0.1
		i=$(( i + 1 ))
	done
	return 1
}

start() {
	ebegin &quot;Starting hotspot&quot;

	# USB 网卡由 udev 异步注册，开机时未必已经就绪，所以轮询等待（上限 15 秒）
	local i=0
	while [ &quot;$i&quot; -lt 150 ]; do
		ip link show &quot;$IFACE&quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&amp;amp; break
		sleep 0.1
		i=$(( i + 1 ))
	done
	if ! ip link show &quot;$IFACE&quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
		eerror &quot;接口 $IFACE 在 15 秒内未出现，热点无法启动&quot;
		return 1
	fi

	ip link set &quot;$IFACE&quot; up
	ip addr add &quot;$GATEWAY/24&quot; dev &quot;$IFACE&quot; 2&amp;gt;/dev/null

	# --- dnsmasq ---
	dnsmasq --conf-file=/etc/dnsmasq.d/hotspot.conf --pid-file=&quot;$DNSMASQ_PID&quot;
	if ! _wait_pidfile &quot;$DNSMASQ_PID&quot; 5; then
		eerror &quot;dnsmasq 启动失败或未在 5 秒内就绪&quot;
		return 1
	fi

	# --- hostapd ---
	hostapd -B -P &quot;$HOSTAPD_PID&quot; /etc/hostapd/hostapd_2g.conf
	if ! _wait_pidfile &quot;$HOSTAPD_PID&quot; 10; then
		ewarn &quot;hostapd 未在 10 秒内就绪（可能需要更久初始化射频），但它已在后台运行&quot;
	fi

	eend 0
}

stop() {
	ebegin &quot;Stopping hotspot&quot;
	pkill -f &quot;hostapd.*hostapd_2g.conf&quot; 2&amp;gt;/dev/null || true
	pkill -f &quot;dnsmasq.*hotspot.conf&quot; 2&amp;gt;/dev/null || true
	rm -f &quot;$HOSTAPD_PID&quot; &quot;$DNSMASQ_PID&quot; 2&amp;gt;/dev/null || true
	ip addr del &quot;$GATEWAY/24&quot; dev &quot;$IFACE&quot; 2&amp;gt;/dev/null || true
	eend 0
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;启用服务&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;sudo chmod +x /etc/init.d/hotspot
sudo rc-update add hotspot default
sudo rc-service hotspot start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;hotspot&lt;/code&gt; 是 &lt;code&gt;rc_need=&quot;net&quot;&lt;/code&gt;，等网络就绪才会启动。&lt;/p&gt;
&lt;p&gt;如果你是用 nftables 管理 NAT，还要把它加进开机流程，做法见前面 NAT 那节。&lt;/p&gt;
&lt;p&gt;用 systemd 的发行版则需把上面的 &lt;code&gt;start&lt;/code&gt;/&lt;code&gt;stop&lt;/code&gt; 写成 service unit。别的 OpenRC 发行版思路相同，但网络服务名和配置路径未必一致——本文的 &lt;code&gt;rc_need=&quot;net&quot;&lt;/code&gt; 依赖 Gentoo netifrc 提供的 &lt;code&gt;net&lt;/code&gt; 虚拟服务，Alpine 上对应的服务叫 &lt;code&gt;networking&lt;/code&gt;，照抄前先确认。&lt;/p&gt;
&lt;h2&gt;验证&lt;/h2&gt;
&lt;p&gt;服务起来之后，按顺序检查，哪一步断了就对应哪一段配置：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一步：服务都活着。&lt;/strong&gt; 本机上看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rc-service hotspot status
pgrep -af hotspot          # 应该能看到 dnsmasq 和 hostapd 各一个
ip -4 addr show wlan0      # 应该能看到 192.168.42.1/24
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;wlan0&lt;/code&gt; 上没有 &lt;code&gt;192.168.42.1/24&lt;/code&gt;，说明 &lt;code&gt;hotspot&lt;/code&gt; 的 &lt;code&gt;start&lt;/code&gt; 没走完，往上翻它启动时的报错。&lt;/p&gt;
&lt;p&gt;顺手确认 NAT 规则在：nftables 用 &lt;code&gt;sudo nft list table ip hotspot_nat&lt;/code&gt;，iptables 用 &lt;code&gt;sudo iptables -t nat -L POSTROUTING -n&lt;/code&gt;，能看到 masquerade 就行。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二步：手机拿到了地址。&lt;/strong&gt; 手机连上热点后，看它分配的 IP 是不是 &lt;code&gt;192.168.42.100&lt;/code&gt;–&lt;code&gt;192.168.42.200&lt;/code&gt; 之间的地址。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果连不上热点：hostapd 没起来，看「无线接口被占用」和「网卡被 rfkill 软阻塞」两节&lt;/li&gt;
&lt;li&gt;如果连上了但一直转圈拿不到 IP：dnsmasq 没应答，看 &lt;code&gt;/var/log/dnsmasq-hotspot.log&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;第三步：能通到上游。&lt;/strong&gt; 在手机上依次 ping 三个地址，断在哪一层很清楚：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;目标&lt;/th&gt;
&lt;th&gt;通了说明&lt;/th&gt;
&lt;th&gt;不通说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;192.168.42.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;到本机这一跳正常&lt;/td&gt;
&lt;td&gt;&lt;code&gt;wlan0&lt;/code&gt; 地址或 dnsmasq 网关选项有问题&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;223.5.5.5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;转发和 NAT 都正常&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ip_forward&lt;/code&gt; 没开，或 NAT / 转发规则没生效&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;任意域名&lt;/td&gt;
&lt;td&gt;DNS 解析也正常&lt;/td&gt;
&lt;td&gt;DNS 不通，检查 &lt;code&gt;dhcp-option=6&lt;/code&gt; 下发的是否可达&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;192.168.42.1&lt;/code&gt; 通、&lt;code&gt;223.5.5.5&lt;/code&gt; 不通，先查 NAT 和转发这一层：回到 NAT 那节确认规则真的加载了（&lt;code&gt;nft list ruleset&lt;/code&gt; 或 &lt;code&gt;iptables -t nat -L POSTROUTING -n&lt;/code&gt;），以及 &lt;code&gt;net.ipv4.ip_forward&lt;/code&gt; 是 &lt;code&gt;1&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;最后：重启再走一遍。&lt;/strong&gt; 上面几步只证明了这一次运行是好的。快照没 &lt;code&gt;save&lt;/code&gt;、&lt;code&gt;rc-update&lt;/code&gt; 没加上、dhcpcd 又抢了地址，这些问题全都要等重启才会暴露。&lt;code&gt;sudo reboot&lt;/code&gt; 之后按第一步和第三步复查一遍，都正常才算真的搭好了。&lt;/p&gt;
&lt;h2&gt;故障排除&lt;/h2&gt;
&lt;h3&gt;无线接口被占用&lt;/h3&gt;
&lt;p&gt;如果这块网卡之前当客户端用过，&lt;code&gt;net.wlan0&lt;/code&gt; 服务或 &lt;code&gt;wpa_supplicant&lt;/code&gt; 进程可能还握着它。此时 hostapd 会报 &lt;code&gt;nl80211: Interface wlan0 is in use&lt;/code&gt; 这样的错误。先确认：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rc-service net.wlan0 status
pgrep -a wpa_supplicant
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果有就停掉，再重启热点：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo rc-service net.wlan0 stop
sudo pkill wpa_supplicant
sudo rc-service hotspot restart
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;网卡被 rfkill 软阻塞&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rfkill list&lt;/code&gt; 里 &lt;code&gt;Soft blocked: yes&lt;/code&gt; 时 hostapd 也起不来：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rfkill list
sudo rfkill unblock wlan
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果看到的是 &lt;code&gt;Hard blocked: yes&lt;/code&gt;，那是机身上的物理开关或 BIOS 关掉了无线，软件解不开，得先去把开关打开。&lt;/p&gt;
&lt;h3&gt;dhcpcd 抢占地址&lt;/h3&gt;
&lt;p&gt;dhcpcd 可能会在这块网卡上尝试 DHCP，失败后留下一个 &lt;code&gt;169.254.x.x&lt;/code&gt; 的地址和 &lt;code&gt;/16&lt;/code&gt; 路由。因此需要在 &lt;code&gt;/etc/dhcpcd.conf&lt;/code&gt; 里加一行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;denyinterfaces wlan0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后重启 dhcpcd，注意要加 &lt;code&gt;--nodeps&lt;/code&gt;。dhcpcd 被 &lt;code&gt;hotspot&lt;/code&gt;、&lt;code&gt;libvirtd&lt;/code&gt;、&lt;code&gt;tailscale&lt;/code&gt; 的服务引用，普通 &lt;code&gt;rc-service dhcpcd restart&lt;/code&gt; 会让 OpenRC 先把这些依赖服务停掉，却不会自动拉起来，结果是热点、tailscale、虚拟机一起掉线，&lt;code&gt;wlan0&lt;/code&gt; 上的 &lt;code&gt;192.168.42.1/24&lt;/code&gt; 也会消失。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo rc-service dhcpcd --nodeps restart
ip -4 addr show wlan0     # 确认没有 169.254.x.x 残留
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果之前已经产生过 &lt;code&gt;169.254.x.x&lt;/code&gt;，&lt;code&gt;denyinterfaces&lt;/code&gt; 不会自动删掉它，只能手动清理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo ip addr del 169.254.x.x/16 dev wlan0
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;日常管理&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo rc-service hotspot  start     # 开热点
sudo rc-service hotspot  stop      # 关热点（NAT 规则保留，但此时无流量匹配）
sudo rc-service hotspot  restart   # 重启热点
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;改完 NAT / 防火墙规则后，按你所用工具的方式重载。以 nftables 为例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nft -f /etc/nftables.conf     # 立即生效
sudo nft list ruleset              # 确认规则在
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;如果用的是前面提到的 Gentoo 官方快照模型，还要再 &lt;code&gt;sudo rc-service nftables save&lt;/code&gt; 一次&lt;/strong&gt;，否则重启后会回退到上一次快照。&lt;/p&gt;
&lt;p&gt;周围 AP 多、连接不稳时可以换信道。默认 &lt;code&gt;channel=6&lt;/code&gt;，换成 1 或 11 通常明显好些，改完执行 &lt;code&gt;sudo rc-service hotspot restart&lt;/code&gt; 生效。&lt;/p&gt;
</content:encoded></item><item><title>我在gentoo下的nftables防火墙设计</title><link>https://cyclicspace.site/posts/nftables-firewall-setup/</link><guid isPermaLink="true">https://cyclicspace.site/posts/nftables-firewall-setup/</guid><description>在Gentoo/OpenRC上接管官方nftables服务：把手写规则作为唯一来源、用CONFIG_PROTECT机制在升级中保住自己的脚本，以及与自带规则的服务如何共存。</description><pubDate>Fri, 19 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;前言&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;此文章用于记录我自己维护防火墙的方法，记录在Gentoo/OpenRC环境下维护防火墙时逐渐形成的思路。&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;一些说明&lt;/h2&gt;
&lt;p&gt;gentoo发行版有自己官方的nftables服务，通常执行&lt;code&gt;rc-update add nftables default&lt;/code&gt;即可使用，但随着我的需求增大，不少端口我都需要手动控制，比如sunshine串流，热点配置等，此时官方的save/restore模型就不够用了。&lt;/p&gt;
&lt;p&gt;portage中有&lt;code&gt;etc-update&lt;/code&gt;机制，正确设置可以保证修改不会被重新&lt;code&gt;emerge nftables&lt;/code&gt;冲掉。下面我先说官方的配置具体是怎样的，再说怎么接管nftables服务。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;官方配置&lt;/h2&gt;
&lt;p&gt;gentoo 的 nftables 服务是快照模型：先把规则装进内核，然后&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo rc-service nftables save
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它会把 &lt;code&gt;nft list ruleset&lt;/code&gt; 的输出写进 &lt;code&gt;/var/lib/nftables/rules-save&lt;/code&gt;，开机时再从这个文件读回来。ebuild 装完提示的也是这个用法。&lt;/p&gt;
&lt;p&gt;加载那一步实际执行的是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;printf &apos;flush ruleset\ninclude &quot;%s&quot;\n&apos; &quot;${NFTABLES_SAVE}&quot; | nft -f -
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;flush ruleset&lt;/code&gt; 是写死在 &lt;code&gt;/usr/libexec/nftables/nftables.sh&lt;/code&gt; 里的，改 &lt;code&gt;/etc/conf.d/nftables&lt;/code&gt; 也去不掉。在快照模型下这么做其实是合理的，因为快照本身是全量的，机器上所有表都在里面，清空再整体装回来也不会丢东西。
但我的用法不是这样。tailscale、libvirt 等软件会往内核里加入自己的防火墙配置，这种情况下官方的一条 &lt;code&gt;flush ruleset&lt;/code&gt; 就会把它们的表一起清掉，结果可想而知，tailnet 不通、虚拟机没网，用&lt;code&gt;rc-service&lt;/code&gt;看状态又全是 started，很容易往错的方向查。为了避免这些问题，所以我接下来打算接管官方服务。&lt;/p&gt;
&lt;h2&gt;接管官方服务&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;/etc/init.d/nftables&lt;/code&gt; 属于 &lt;code&gt;net-firewall/nftables&lt;/code&gt; 这个包，但它在 &lt;code&gt;/etc&lt;/code&gt; 里，而 &lt;code&gt;/etc&lt;/code&gt; 是配置目录，不是包来管理的。portage 对待配置目录的规则写在 emerge(1) 里：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The purpose of this feature is to prevent new package installs from clobbering existing configuration files.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;具体做法是，安装时如果发现同名文件已经存在，就把要装的那个改名成 &lt;code&gt;._cfg0000_foo&lt;/code&gt; 放在旁边，等用户自己决定怎么合并。所以升级一个包&lt;strong&gt;不会&lt;/strong&gt;动改过的文件，只会在旁边多放一个待合并的新版本。这是设计出来的行为，不是副作用。&lt;/p&gt;
&lt;p&gt;而且这里还有一层。make.conf(5) 里有个默认开启的 FEATURES：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;config-protect-if-modified
This causes the CONFIG_PROTECT behavior to be skipped for files that have not been modified since they were installed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;意思是，如果某个文件从装好到现在都没有被修改过(mtime)，portage 就会认为没必要保护它，升级时直接换成新的；该文件一旦修改过，它从此就会进入保护状态，生成 &lt;code&gt;._cfg0000_&lt;/code&gt; 并询问用户选择如何处理。&lt;/p&gt;
&lt;p&gt;所以直接把自己的逻辑写进 &lt;code&gt;/etc/init.d/nftables&lt;/code&gt; 是比较合理的做法，服务名保持不变，用起来也几乎感受不到区别。&lt;/p&gt;
&lt;p&gt;但要千万注意执行etc-update命令后提示到此文件需要更新时要看清楚，千万不要选-3。选-3会用官方脚本把你这份覆盖掉，而官方脚本加载时执行的是 &lt;code&gt;flush ruleset&lt;/code&gt; 加上 include 那个 0 字节的 &lt;code&gt;rules-save&lt;/code&gt;，结果将会是&lt;strong&gt;清空全部表、且不加载任何规则，机器变成完全没有防火墙&lt;/strong&gt;。而且 &lt;code&gt;-3&lt;/code&gt; 是全局覆盖，作用于整个扫描范围，一次会把所有包所有待合并文件全部覆盖。为了保险还是建议手动创建备份文件&lt;code&gt;cp -a /etc/init.d/nftables /etc/init.d/nftables.bak&lt;/code&gt;，用于防止手贱选了-3选项配置被清除后没有及时做备份。&lt;/p&gt;
&lt;h2&gt;服务脚本&lt;/h2&gt;
&lt;p&gt;以下配置仅供参考：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/sbin/openrc-run
# ============================================================================
#  /etc/init.d/nftables
#
#  作用: 加载 /etc/nftables.conf, 只管理我自己的表。
#
#  升级注意:
#    /etc 在 CONFIG_PROTECT 里, 升级本包时会在旁边生成
#    /etc/init.d/._cfg0000_nftables。合并时选 -7 即可保留本脚本:
#        sudo etc-update /etc/init.d
# ============================================================================

description=&quot;nftables firewall (single source: /etc/nftables.conf)&quot;

NFT_FILE=&quot;/etc/nftables.conf&quot;

# 写成 &quot;族:表名&quot; 的形式, 空格分隔; 要与 nftables.conf 里的定义保持一致。
MY_TABLES=&quot;inet:&amp;lt;过滤表&amp;gt; ip:&amp;lt;NAT表&amp;gt;&quot;

extra_commands=&quot;check&quot;
extra_started_commands=&quot;check reload&quot;

depend() {
	need localmount
	before net
}

check() {
	ebegin &quot;语法检查 ${NFT_FILE}&quot;
	nft -c -f &quot;${NFT_FILE}&quot;
	eend $? &quot;语法/语义有问题, 上面是报错位置&quot;
}

start() {
	ebegin &quot;加载 nftables 规则 (${NFT_FILE})&quot;
	nft -f &quot;${NFT_FILE}&quot;
	eend $? &quot;加载失败 —— 当前处于无防火墙状态&quot;
}

stop() {
	ebegin &quot;移除本服务的表 (${MY_TABLES})&quot;
	for t in ${MY_TABLES}; do
		fam=&quot;${t%%:*}&quot;
		name=&quot;${t##*:}&quot;
		# 先确认存在再删, 保证 stop 可以重复执行。
		if nft list table &quot;${fam}&quot; &quot;${name}&quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
			nft delete table &quot;${fam}&quot; &quot;${name}&quot; || true
		fi
	done
	eend 0
}

reload() {
	ebegin &quot;重新加载 nftables 规则 (${NFT_FILE})&quot;
	nft -f &quot;${NFT_FILE}&quot;
	eend $? &quot;重载失败, 旧规则仍在生效&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;记得将&lt;code&gt;MY_TABLES&lt;/code&gt; 两处占位符换成在 &lt;code&gt;/etc/nftables.conf&lt;/code&gt; 里定义的实际表名，否则 &lt;code&gt;stop&lt;/code&gt; 时查不到表会直接跳过。&lt;/p&gt;
&lt;p&gt;写好后再给&lt;code&gt;/etc/init.d/nftables&lt;/code&gt;可执行权限，加进 default 运行级，再启动一次：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo chmod +x /etc/init.d/nftables
sudo rc-update add nftables default
sudo rc-service nftables start
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;配合其他软件的防火墙配置来管理自己的防火墙规则&lt;/h2&gt;
&lt;p&gt;tailscale、libvirt 等等其他软件都有自己的一套防火墙配置。这些配置通常不需要也不建议用户来手动更改，它们启动停止时自己会处理。&lt;/p&gt;
&lt;p&gt;所以用户在管理nftables时只需遵守以下原则：&lt;/p&gt;
&lt;p&gt;1、不随意执行sudo nft flush ruleset&lt;/p&gt;
&lt;p&gt;2、排除防火墙问题时检查是否与软件自带的防火墙配置有冲突&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nft list tables
sudo nft list chain ip filter
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;nft list tables&lt;/code&gt; 列出的表通常比自己的多，看一眼链名就能认出是谁建的，比如 &lt;code&gt;ts-input&lt;/code&gt;、&lt;code&gt;ts-forward&lt;/code&gt; 是 tailscale 的。自己的表名带上能一眼区分的名字，查问题的时候省事。&lt;/p&gt;
&lt;p&gt;还有一类误判是容器。网上很多配置会写 &lt;code&gt;iifname &quot;podman*&quot; accept&lt;/code&gt;、&lt;code&gt;oifname &quot;veth*&quot; accept&lt;/code&gt; 之类的转发规则，但那是 rootful 加 bridge 网络才有意义。用 rootless 配 pasta 的话，容器流量在内核看来就是本机进程自己发出去的，走 output 链，根本不经过 forward。那些规则不会生效，纯粹是死代码。先看一眼有没有网桥接口就知道自己属于哪种：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip -br link
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;日常维护&lt;/h2&gt;
&lt;p&gt;改完先检查再加载：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nft -c -f /etc/nftables.conf
sudo rc-service nftables reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ct state established,related accept&lt;/code&gt; 每个链都应该要有。它放行本机主动发起的连接的回程包，不用给每个服务写双向规则。forward 链上漏了这条，表现是有 IP、能解析域名，但所有网页都打不开 —— 因为回程包没有任何规则能匹配上。&lt;/p&gt;
&lt;p&gt;重建表用 &lt;code&gt;destroy&lt;/code&gt; 而不是 &lt;code&gt;flush&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;destroy table inet &amp;lt;过滤表&amp;gt;
destroy table ip &amp;lt;NAT表&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;destroy&lt;/code&gt; 只删指定的表，表不存在也不报错，适合每次全量加载；&lt;code&gt;flush ruleset&lt;/code&gt; 会把别人的表一起清掉。&lt;/p&gt;
&lt;p&gt;平时不用手动 start，服务已经在 default 运行级里了，开机自己会加载。&lt;code&gt;start&lt;/code&gt; 只在手动 stop 过之后才需要。&lt;/p&gt;
&lt;p&gt;若想加一个新服务的端口，顺序是先用&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ss -tulnp | grep &amp;lt;关键字&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看清楚它实际监听的是什么协议、哪个端口，再把对应端口加进 &lt;code&gt;/etc/nftables.conf&lt;/code&gt;。&lt;/p&gt;
</content:encoded></item><item><title>Gentoo 安装记录</title><link>https://cyclicspace.site/posts/gentoo_install/</link><guid isPermaLink="true">https://cyclicspace.site/posts/gentoo_install/</guid><description>记录一次 Gentoo 安装过程及配置（Btrfs + Openrc + 自定义内核）</description><pubDate>Sun, 15 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;gentoo-installation-steps&lt;/h1&gt;
&lt;h2&gt;gentoo linux安装记录&lt;/h2&gt;
&lt;h3&gt;引言&lt;/h3&gt;
&lt;p&gt;记录一次安装gentoo的过程，文档中可能存在不太合理的部分。请以官方文档为准，本篇文章只能作为参考。
先说我的安装条件&lt;br /&gt;
&lt;strong&gt;Gentoo版本&lt;/strong&gt;： [Gentoo Linux 23.0/openrc]&lt;br /&gt;
&lt;strong&gt;内核版本&lt;/strong&gt;： [7.2.2-cachyos-r4]&lt;br /&gt;
&lt;strong&gt;文件系统&lt;/strong&gt;： [btrfs,vfat]&lt;br /&gt;
&lt;strong&gt;启动方式&lt;/strong&gt;： [UEFI+grub]&lt;/p&gt;
&lt;h3&gt;硬件信息&lt;/h3&gt;
&lt;p&gt;处理器 [AMD Ryzen r3 3300x]&lt;br /&gt;
显卡 [AMD Radeon RX5700]&lt;br /&gt;
内存 [16GB DDR4]&lt;br /&gt;
硬盘 [256GB NVMe SSD]&lt;/p&gt;
&lt;h3&gt;准备工作&lt;/h3&gt;
&lt;p&gt;选择合适的方法安装Gentoo&lt;br /&gt;
Gentoo可以以许多不同的方式安装。&lt;br /&gt;
它可以从官方Gentoo安装介质（如我们的可引导ISO文件）下载和安装。安装介质可以安装在USB盘上或通过网络引导环境访问。 或者，Gentoo可以从非官方介质安装，如已安装的发行版或非Gentoo可启动磁盘（如 Linux Mint）。&lt;br /&gt;
Gentoo LiveGUI提供 KDE 桌面环境的 LiveGUI 可能会使一些用户更容易安装 Gentoo。除了提供好用的桌面环境，LiveGUI 通过 NetworkManager 组件也提供了简单的 WiFi 设置。&lt;br /&gt;
我是先去https://mirrors.ustc.edu.cn/gentoo/releases/amd64/autobuilds/ 下载iso镜像，选install-amd64-minimal和livegui-amd64都行。我用livegui-amd64，方便复制粘贴。&lt;/p&gt;
&lt;p&gt;下载后使用烧录工具将镜像写入到u盘。&lt;/p&gt;
&lt;h3&gt;进入livecd&lt;/h3&gt;
&lt;p&gt;插入写好镜像的u盘，进入live系统，连接wifi或插上网线。&lt;/p&gt;
&lt;p&gt;打开konsole命令控制台，输入&lt;br /&gt;
&lt;code&gt;sudo passwd&lt;/code&gt; # 先设置一个简单管理密码，因为这只是一个临时使用的live系统，非常复杂的密码反而会引起不便。&lt;/p&gt;
&lt;p&gt;输入&lt;code&gt;su&lt;/code&gt;并输入刚才的设置的密码进入root用户。&lt;/p&gt;
&lt;p&gt;接下来给磁盘分区，我用的是fdisk工具，livecd中也自带parted等分区工具，看个人习惯来使用吧。&lt;br /&gt;
**注意！在分区之前务必及时备份数据！&lt;br /&gt;
&lt;code&gt;fdisk /dev/nvme0n1&lt;/code&gt;  # 如果是sata硬盘就应该是/dev/sda1&lt;br /&gt;
以下是我的分区方案（仅供参考）&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Disk /dev/nvme0n1: 232.89 GiB, 250059350016 bytes, 488397168 sectors
Disk model: WDC WDS250G2B0C-00PXH0
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 2A4768D8-9813-4CE2-BE64-1CB13C1F959A

Device           Start       End   Sectors   Size Type
/dev/nvme0n1p1    2048   1050623   1048576   512M EFI System
/dev/nvme0n1p2 1050624 488396799 487346176 232.4G Linux filesystem
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;格式化分区&lt;br /&gt;
&lt;code&gt;mkfs.vfat -F 32 /dev/nvme0n1p1&lt;/code&gt; # 给nvme0n1p2使用vfat文件系统&lt;br /&gt;
&lt;code&gt;mkfs.btrfs -f /dev/nvme0n1p2&lt;/code&gt; # 给nvme0n1p1使用btrfs文件系统&lt;/p&gt;
&lt;p&gt;之后给nvme0n1p2细分btrfs子卷&lt;br /&gt;
&lt;code&gt;mkdir -p /mnt/btrfs&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount -o subvolid=5 /dev/nvme0n1p2 /mnt/btrfs&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;cd /mnt/btrfs&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;btrfs subvolume create @&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;btrfs subvolume create @home&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;btrfs subvolume create @boot&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;btrfs subvolume create @var&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;btrfs subvolume create @snapshots&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;btrfs subvolume set-default @ /mnt/btrfs&lt;/code&gt;   # 设 @ 为默认子卷&lt;br /&gt;
&lt;code&gt;btrfs subvolume list /mnt/btrfs&lt;/code&gt;            # 验证一下&lt;br /&gt;
&lt;code&gt;umount /mnt/btrfs&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;挂载&lt;br /&gt;
&lt;code&gt;mount -o subvol=@,compress=zstd:1,commit=30,ssd,discard=async,space_cache=v2 /dev/nvme0n1p2 /mnt/gentoo&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mkdir -p /mnt/gentoo/{boot/efi,home,var}&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount -o subvol=@boot   /dev/nvme0n1p2 /mnt/gentoo/boot&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount -o subvol=@home,nodatacow /dev/nvme0n1p2 /mnt/gentoo/home&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount -o subvol=@var,nodatacow   /dev/nvme0n1p2 /mnt/gentoo/var&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount -o subvol=@snapshots       /dev/nvme0n1p2 /mnt/gentoo/.snapshots&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount /dev/nvme0n1p1 /mnt/gentoo/boot/efi &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;进到刚挂载好的目录&lt;br /&gt;
&lt;code&gt;cd /mnt/gentoo&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;安装 Gentoo 安装文件&lt;/h3&gt;
&lt;p&gt;下载stage3压缩包&lt;br /&gt;
&lt;code&gt;links https://mirrors.ustc.edu.cn/gentoo/releases/amd64/autobuilds/&lt;/code&gt;  #在里面选择显示日期和时间的目录后回车，比如20260308T170100Z，这个显示日期和时间的目录一般会有好几个，我一般选择的是最新的，避免更新时间长。例如，我用systemd就选择stage3-amd64-systemd-20260308T170100Z.tar.xz&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tar xpvf stage3-amd64-systemd-20250914T170345Z.tar.xz&lt;/code&gt; # 解压&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nano -w /mnt/gentoo/etc/portage/make.conf&lt;/code&gt;  # 设置gcc编译选项&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# detailed example.
COMMON_FLAGS=&quot;-march=native -O3 -pipe -finline-functions&quot; #我用gcc -O3优化
CFLAGS=&quot;${COMMON_FLAGS}&quot;
CXXFLAGS=&quot;${COMMON_FLAGS}&quot;
FCFLAGS=&quot;${COMMON_FLAGS}&quot;
FFLAGS=&quot;${COMMON_FLAGS}&quot;
#CPU_FLAGS_X86=&quot;&quot; # 此项待会再填
MAKEOPTS=&quot;-j9 -l8&quot; #3300x有8线程，如果没有设置zram怕内存溢出导致livecd卡死就保守一点用-j6

# NOTE: This stage was built with the bindist USE flag enabled

# This sets the language of build output to English.
# Please keep this setting intact when reporting bugs.
LC_MESSAGES=C.utf8

CHOST=&quot;x86_64-pc-linux-gnu&quot;
EMERGE_DEFAULT_OPTS=&quot;--with-bdeps=y --verbose=y --keep-going&quot;
ACCEPT_LICENSE=&quot;*&quot;
ACCEPT_KEYWORDS=&quot;amd64&quot;
L10N=&quot;en-US zh-CN en zh&quot;
LINGUAS=&quot;en-US zh-CN en zh&quot;
AUTO_CLEAN=&quot;yes&quot;
GRUB_PLATFORMS=&quot;efi-64&quot;
VIDEO_CARDS=&quot;amdgpu radeonsi&quot;
ALSA_CARDS=&quot;hda-intel&quot;
INPUT_DEVICES=&quot;evdev&quot;

PORTAGE_NICENESS=&quot;15&quot;

GENTOO_MIRRORS=&quot;https://mirrors.tuna.tsinghua.edu.cn/gentoo https://mirrors.zju.edu.cn/gentoo/ http://mirrors.zju.edu.cn/gentoo/ https://mirrors.ustc.edu.cn/gentoo/ https://mirrors.nju.edu.cn/gentoo/ http://mirrors.nju.edu.cn/gentoo/ https://mirror.lzu.edu.cn/gentoo http://mirror.lzu.edu.cn/gentoo https://mirrors.aliyun.com/gentoo/ http://mirrors.aliyun.com/gentoo/ https://mirrors.163.com/gentoo/ http://mirrors.163.com/gentoo/ &quot;


#gentoo的特色之一，gentoo的大部分软件包都会有不同的USE标志，在这里的设置是全局的，意思是你要给所有支持这个USE标志的软件包都默认启用这个标志，如果你只希望给单独的软件包设置特定的USE标志，别急，我后面点会讲到。
#USE=&quot;-pulseaudio -iptables -pipewire -jack -kde -gnome -xfce -wayland fortran lto pgo graphite openmp minizip elogind dbus policykit X cjk vdpau vaapi vulkan egl gles2 glfw opengl openal alsa nftables&quot; #这是我会用到的USE标志，仅供参考。而且不推荐在刚安装系统时就同时启用这么多标志。这些后续我会一点一点的加上。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配置软件镜像源
&lt;code&gt;mkdir -p -v /mnt/gentoo/etc/portage/repos.conf&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;cp -v /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nano -w /mnt/gentoo/etc/portage/repos.conf/gentoo.conf&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[DEFAULT]
main-repo = gentoo
sync-uri = rsync://mirrors.ustc.edu.cn/gentoo-portage #加入中国源

[gentoo]
location = /var/db/repos/gentoo
...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;安装 Gentoo 基础系统&lt;/h3&gt;
&lt;p&gt;复制DNS信息&lt;br /&gt;
&lt;code&gt;cp --dereference /etc/resolv.conf /mnt/gentoo/etc/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;挂载系统必要环境，并进入Chroot环境&lt;br /&gt;
&lt;code&gt;mount --types proc /proc /mnt/gentoo/proc&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --rbind /sys /mnt/gentoo/sys&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --make-rslave /mnt/gentoo/sys&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --rbind /dev /mnt/gentoo/dev&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --make-rslave /mnt/gentoo/dev&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --rbind /run /mnt/gentoo/run&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --make-rslave /mnt/gentoo/run&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;chroot /mnt/gentoo /bin/bash&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mkdir -p /var/db/repos/gentoo&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;env-update&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;source /etc/profile&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;export PS1=&quot;(chroot) ${PS1}&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;安装 Gentoo ebuild 存储库的快照。该快照包含一组文件，这些文件通知 Portage 可用的软件标题（用于安装）、系统管理员可以选择的配置文件、打包或配置文件特定的新闻项目等。&lt;br /&gt;
&lt;code&gt;emerge-webrsync&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;安装cpuid2cpuflags，检测cpu指令集&lt;br /&gt;
&lt;code&gt;emerge --ask app-portage/cpuid2cpuflags&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;cpuid2cpuflags&lt;/code&gt;  # 将输出值全部拷贝到/mnt/gentoo/etc/portage/make.conf中，作为“CPU_FLAGS_X86= ”的值，并取消对“CPU_FLAGS_X86= ”这一行的注释。&lt;/p&gt;
&lt;p&gt;配置系统时区&lt;br /&gt;
&lt;code&gt;nano -w /etc/locale.gen&lt;/code&gt;&lt;br /&gt;
将以下几项取消注释，如果没有就手动加上&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;en_US ISO-8859-1
en_US.UTF-8 UTF-8
zh_CN GBK 
zh_CN.UTF-8 UTF-8
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;下一步是运行 locale-gen 命令。此命令生成 /etc/locale.gen 文件中指定的所有语言环境。&lt;br /&gt;
&lt;code&gt;locale-gen&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;（可选）重新将整个基本系统从stage1编译到stage3&lt;/h3&gt;
&lt;p&gt;目的是把原来官方提供的所有组件替换成自己编译的（包括GCC编译器和所有基本系统组件），这样一来整个系统的所有程序和组件都是针对自己电脑CPU架构优化编译的了，争取性能最大化。唯一的坏处就是会花费更多的精力和时间。如果你只是想简单的安装gentoo系统体验一下，就推荐跳过此步骤。&lt;br /&gt;
&lt;code&gt;./var/db/repos/gentoo/scripts/bootstrap.sh&lt;/code&gt;  # 这个脚本执行完检测后重新编译安装emerge包管理器，在我这台机器上花费了十多分钟的时间。&lt;/p&gt;
&lt;p&gt;重新编译安装完emerge包管理器后，bootstrap.sh脚本还会继续检测当前系统环境，最后很可能会警告提示你当前系统里的gcc编译器缺少对fortran的支持、zlib库缺少对minizip的支持，然后退出脚本。&lt;br /&gt;
&lt;code&gt;nano -w /etc/portage/make.conf&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
USE=&quot;fortran lto pgo graphite openmp minizip&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;先启用以上USE标志，其他USE标志继续注释着先。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;emerge --ask gcc&lt;/code&gt; # 重新编译gcc，你会看到你会看到刚才加上的那些use标志高亮了，意味着这次编译会应用上这些use标志。这会花费很长时间，大约2-3个小时吧。&lt;/p&gt;
&lt;p&gt;之后退出当前chroot环境再重新进入。&lt;br /&gt;
&lt;code&gt;exit&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;chroot /mnt/gentoo /bin/bash&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;env-update &amp;amp;&amp;amp; source /etc/profile &amp;amp;&amp;amp; export PS1=&quot;(chroot) ${PS1}&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;重新运行一次脚本检测。&lt;br /&gt;
&lt;code&gt;./var/db/repos/gentoo/scripts/bootstrap.sh&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;不出意外的话最后会成功通过检测，并提示你系统已经成功“bootstrapped”了，并要求你执行emerge -e @system。那我们就从stage2到stage3（重新编译：基本系统的所有组件base system）。&lt;br /&gt;
&lt;code&gt;emerge -e @system&lt;/code&gt;
&lt;code&gt;emerge -e @world&lt;/code&gt;  # 此过程将会非常耗时，3300x编译大约用了2个半小时&lt;/p&gt;
&lt;h3&gt;接下来，正式安装gentoo系统 （如果选择跳过上面的可选步骤就直接从这里继续）&lt;/h3&gt;
&lt;p&gt;到这里就可以把make.conf文件中剩下的use都启用上了，然后更新一下。&lt;br /&gt;
&lt;code&gt;emerge -avuDN @world&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;eselect profile list&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;eselect profile set X&lt;/code&gt;  # 我打算用openrc+窗口管理器，所以选了default/linux/amd64/23.0/，有其他需求的就选择其他对应的profile&lt;br /&gt;
&lt;code&gt;env-update&lt;/code&gt;&lt;br /&gt;
如果profile发生了改变，也应该再次更新软件包。&lt;br /&gt;
&lt;code&gt;emerge -avuDN @world&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;设置系统locale&lt;br /&gt;
&lt;code&gt;eselect locale list&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;eselect locale set X&lt;/code&gt;  # 这里建议选择en-US.utf8，大部分TTY终端都不支持中文。&lt;/p&gt;
&lt;p&gt;创建并配置/etc/fstab文件，用以指示系统开机自动挂载的必要设备/分区&lt;br /&gt;
&lt;code&gt;blkid &amp;gt;&amp;gt; /etc/fstab&lt;/code&gt;  # 将输出结果追加到fstab配置文件末尾，然后根据追加的内容进行下述修改&lt;br /&gt;
&lt;code&gt;nano -w /etc/fstab&lt;/code&gt;  # 请参考我的配置，建议使用uuid的形式设置（不建议使用/dev/sdX？的形式）(是uuid，而不是partuuid哦)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# &amp;lt;fs&amp;gt;			                           &amp;lt;mountpoint&amp;gt;	&amp;lt;type&amp;gt; &amp;lt;opts&amp;gt;		                                              &amp;lt;dump&amp;gt; &amp;lt;pass&amp;gt;
UUID=bd7589dd-daa7-4245-9ce5-4d1cc9e128cb  /            btrfs  defaults,noatime,ssd,commit=60,nodiscard,subvol=@          0 0
UUID=bd7589dd-daa7-4245-9ce5-4d1cc9e128cb  /home        btrfs  defaults,noatime,ssd,commit=60,nodiscard,subvol=@home      0 0
UUID=bd7589dd-daa7-4245-9ce5-4d1cc9e128cb  /boot        btrfs  defaults,noatime,ssd,commit=60,nodiscard,subvol=@boot      0 0
UUID=bd7589dd-daa7-4245-9ce5-4d1cc9e128cb  /var         btrfs  defaults,noatime,ssd,commit=60,nodiscard,subvol=@var       0 0
UUID=bd7589dd-daa7-4245-9ce5-4d1cc9e128cb  /.snapshots  btrfs  defaults,noatime,ssd,commit=60,nodiscard,subvol=@snapshots 0 0
tmpfs  /tmp  tmpfs  defaults,noatime,mode=1777,size=4G  0 0

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装必须的文件系统支持，否则无法访问硬盘上的分区！！&lt;br /&gt;
&lt;code&gt;emerge --ask sys-fs/e2fsprogs&lt;/code&gt;     #ext4&lt;br /&gt;
&lt;code&gt;emerge --ask sys-fs/xfsprogs&lt;/code&gt;      #xfs&lt;br /&gt;
&lt;code&gt;emerge --ask sys-fs/dosfstools&lt;/code&gt;    #fat32&lt;br /&gt;
&lt;code&gt;emerge --ask sys-fs/ntfs3g&lt;/code&gt;        #ntfs&lt;br /&gt;
&lt;code&gt;emerge --ask sys-fs/fuse-exfat&lt;/code&gt;    #exfat&lt;br /&gt;
&lt;code&gt;emerge --ask sys-fs/exfat-utils&lt;/code&gt;   #exfat&lt;br /&gt;
&lt;code&gt;emerge --ask sys-fs/btrfs-progs&lt;/code&gt;   #btrfs&lt;/p&gt;
&lt;h3&gt;配置 Linux 内核&lt;/h3&gt;
&lt;p&gt;编译内核前，先安装一些必要工具&lt;br /&gt;
&lt;code&gt;emerge --ask eix sudo pciutils usbutils hwinfo gentoolkit euses dev-vcs/git eselect-repository&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;可选工具&lt;br /&gt;
&lt;code&gt;emerge --ask neovim fastfetch zsh bottom&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;下载安装wifi网卡和intel核显的必要驱动固件&lt;br /&gt;
&lt;code&gt;emerge --ask sys-kernel/linux-firmware&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;安装更新Intel CPU的微码文件&lt;br /&gt;
&lt;code&gt;emerge --ask sys-firmware/intel-microcode sys-apps/iucode_tool&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;gentoo的特色之二，就是鼓励自行配置系统内核。&lt;br /&gt;
编译内核的方式与过程多种多样，下面我来详细说说。&lt;br /&gt;
从以下两个方法中选一个。&lt;br /&gt;
第一种方法：直接安装gentoo-kernel-bin软件包&lt;br /&gt;
&lt;code&gt;emerge --ask gentoo-kernel-bin&lt;/code&gt; # 此命令能自动完成内核编译，主打一个方便。但这样的缺点也很明显，没有改变任何内核设置。几乎所有功能都包含在了内核里面。一般想省时省事用这个方法比较合适。&lt;/p&gt;
&lt;p&gt;第二种方法：自定义内核&lt;br /&gt;
使用genkernel工具&lt;br /&gt;
&lt;code&gt;emerge --ask gentoo-sources&lt;/code&gt;  # 先安装内核源码&lt;br /&gt;
&lt;code&gt;emerge --ask genkernel&lt;/code&gt;  # 安装genkernel
&lt;code&gt;eselect kernel list&lt;/code&gt;  # 查看内核&lt;br /&gt;
&lt;code&gt;eselect kernel set X&lt;/code&gt;  # 选择内核&lt;br /&gt;
&lt;code&gt;genkernel --menuconfig kernel&lt;/code&gt;  # 进到linux内核配置界面，genkernel默认使用gentoo-kernel的内核配置，此配置通常开箱即用，你也可以在此基础上做精简，比如精简掉你用不到的网卡、声卡、显卡等驱动和文件系统等。&lt;br /&gt;
除了可以设为N或Y还可以将一些配置以模块形式加载（即设为M）。还请避免过度精简导致开机时内核启动卡住，这时就需要自己排除问题了。&lt;/p&gt;
&lt;p&gt;**TIPS：**genkernel还有一些其他的用法，可以使用genkernel --help来查看或者去看gentoo的genkernel文档，等下就会说到如何用genkernel来配置initramfs，https://wiki.gentoo.org/wiki/Genkernel/zh-cn。&lt;/p&gt;
&lt;p&gt;或者直接进linux内核目录，手动完成整个编译流程&lt;br /&gt;
&lt;code&gt;emerge --ask gentoo-sources&lt;/code&gt;  # 先安装内核源码&lt;br /&gt;
&lt;code&gt;eselect kernel list&lt;/code&gt;  # 查看当前内核&lt;br /&gt;
&lt;code&gt;eselect kernel set X&lt;/code&gt;  # 选择当前内核&lt;br /&gt;
&lt;code&gt;cd /usr/src/linux&lt;/code&gt;  #进入linux内核目录&lt;/p&gt;
&lt;p&gt;(可选)如果之前已经安装过genkernel，会把linux的默认配置换成gentoo-kernel的内核配置，如果只想用linux的默认配置就执行以下命令。&lt;br /&gt;
&lt;code&gt;mv .config bak.config&lt;/code&gt; # 备份gentoo-kernel的内核配置（如果还需要此配置的话）&lt;br /&gt;
&lt;code&gt;make x86_64_defconfig&lt;/code&gt; # 使用linux默认配置&lt;br /&gt;
使用linux默认配置通常不能开箱即用，你需要检查文件系统(vfat、ext4等)、驱动(声卡、网卡、显卡等)、init子系统(systemd or openrc)、启动项(bios or uefi)等配置是否合理开启，只有满足条件内核才能正常启动运行。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;make menuconfig&lt;/code&gt;  # 进入内核配置界面&lt;br /&gt;
&lt;code&gt;make -j6&lt;/code&gt;  #用6线程来编译内核&lt;br /&gt;
&lt;code&gt;make modules_install&lt;/code&gt;  #编译模块&lt;br /&gt;
&lt;code&gt;make install&lt;/code&gt;  #完成整个内核编译过程&lt;/p&gt;
&lt;p&gt;若使用以上第二或第三种方法安装linux内核，可能还需要配置initramfs，可以用genkernel也可以用dracut，推荐用genkernel。&lt;br /&gt;
&lt;code&gt;genkernel --install initramfs&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;使用以上三种方法的任意一种来完成内核安装操作后，一定需要配置引导加载程序。&lt;br /&gt;
配置引导加载程序也有很多种，推荐以grub为主，https://wiki.gentoo.org/wiki/Grub。&lt;br /&gt;
要配置grub，请执行以下命令。&lt;br /&gt;
&lt;code&gt;emerge --ask sys-boot/grub&lt;/code&gt;  # 安装grub&lt;br /&gt;
&lt;code&gt;grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Gentoo&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;grub-mkconfig -o /boot/grub/grub.cfg&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;配置时间&lt;/h3&gt;
&lt;p&gt;systemd随附了&lt;code&gt;timedatectl&lt;/code&gt;命令，用于管理时区，要查看当前时区请执行该命令。&lt;br /&gt;
之后执行&lt;code&gt;timedatectl list-timezones&lt;/code&gt;命令来列出可用的时区。&lt;br /&gt;
要更改时区（例如，更改至德国的时区），使用命令&lt;code&gt;timedatectl set-timezone Europe/Berlin&lt;/code&gt;即可。&lt;/p&gt;
&lt;h3&gt;配置网络&lt;/h3&gt;
&lt;p&gt;emerge --ask dhcpcd&lt;br /&gt;
如果你需要连接无线网络，我推荐iwd这个软件包。&lt;br /&gt;
emerge --ask net-wireless/iwd&lt;br /&gt;
具体请看官方文档，内核配置也要根据文档中的配置来更改。&lt;br /&gt;
https://wiki.gentoo.org/wiki/Iwd&lt;/p&gt;
&lt;p&gt;启动网络服务&lt;br /&gt;
systemctl enable dhcpcd iwd&lt;/p&gt;
&lt;h3&gt;配置系统用户&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;visudo&lt;/code&gt;&lt;br /&gt;
把“%wheel ALL=(ALL) ALL”这一行去掉注释&lt;/p&gt;
&lt;p&gt;&lt;code&gt;useradd -m -G users,wheel,audio,usb,video -s /bin/bash &amp;lt;你的用户名&amp;gt; &lt;/code&gt;&lt;br /&gt;
&lt;code&gt;passwd root&lt;/code&gt; #更改root账户密码&lt;br /&gt;
&lt;code&gt;passwd &amp;lt;你的用户名&amp;gt;&lt;/code&gt; #更改你自己的用户密码&lt;br /&gt;
&lt;code&gt;echo &amp;lt;主机名&amp;gt; &amp;gt; /etc/hostname&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;最后的安装收尾和清理工作，卸载之前挂载的分区&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rm /stage3-*.tar.xz&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;exit&lt;/code&gt; # 退出chroot环境&lt;br /&gt;
&lt;code&gt;umount -lR /mnt/gentoo&lt;/code&gt;&lt;br /&gt;
到此整个gentoo系统就安装结束了，重启电脑进入你的新系统好好享受吧&lt;/p&gt;
&lt;h3&gt;(可选)备份gentoo&lt;/h3&gt;
&lt;p&gt;第一种备份方式：以压缩包形式备份&lt;br /&gt;
切换到根目录&lt;br /&gt;
&lt;code&gt;cd /&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;创建备份（排除临时和虚拟文件系统），可根据自己需要来选择排除掉的文件，比如不需要排除/home中的文件就把--exclude=/home 删掉。&lt;br /&gt;
&lt;code&gt;tar --create --gzip --file /backup.tar.gz --exclude=/backup.tar.gz --exclude=/home --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/run --exclude=/tmp --exclude=/mnt --exclude=/media --exclude=/lost+found /&lt;/code&gt; # 实测从刚安装结束时就压缩文件大小约为2G左右，请自行保存好该压缩包。&lt;/p&gt;
&lt;p&gt;如果你要恢复该备份，请在此之前先保存好自己在该硬盘中想要保存的数据。然后用u盘进livecd系统把原本的系统盘格式化，请务必考虑清楚后再执行以下操作。&lt;br /&gt;
进入livecd环境&lt;br /&gt;
&lt;code&gt;mkfs.btrfs -f /dev/nvme0n1p1&lt;/code&gt; #给nvme0n1p1使用btrfs文件系统&lt;br /&gt;
&lt;code&gt;mkfs.vfat -F 32 /dev/nvme0n1p2&lt;/code&gt; #给nvme0n1p2使用vfat文件系统&lt;br /&gt;
重新挂载分区&lt;br /&gt;
&lt;code&gt;mount /dev/nvme0n1p1 /mnt/gentoo&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mkdir /mnt/gentoo/boot&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount /dev/nvme0n1p2 /mnt/gentoo/boot&lt;/code&gt;&lt;br /&gt;
进到挂载nvme0n1p1的目录&lt;br /&gt;
&lt;code&gt;cd /mnt/gentoo&lt;/code&gt;&lt;br /&gt;
将备份的压缩包复制到/mnt/gentoo目录中。&lt;br /&gt;
&lt;code&gt;cp &amp;lt;你所备份的压缩包路径&amp;gt; ./&lt;/code&gt;&lt;br /&gt;
解压压缩包&lt;br /&gt;
&lt;code&gt;tar xpvf backup.tar.gz&lt;/code&gt;&lt;br /&gt;
复制DNS信息&lt;br /&gt;
&lt;code&gt;cp --dereference /etc/resolv.conf /mnt/gentoo/etc/&lt;/code&gt;&lt;br /&gt;
挂载系统必要环境，并进入Chroot环境&lt;br /&gt;
&lt;code&gt;mount --types proc /proc /mnt/gentoo/proc&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --rbind /sys /mnt/gentoo/sys&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --make-rslave /mnt/gentoo/sys&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --rbind /dev /mnt/gentoo/dev&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --make-rslave /mnt/gentoo/dev&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --rbind /run /mnt/gentoo/run&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mount --make-rslave /mnt/gentoo/run&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;chroot /mnt/gentoo /bin/bash&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;mkdir -p /var/db/repos/gentoo&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;env-update&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;source /etc/profile&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;export PS1=&quot;(chroot) ${PS1}&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;第二种方式：如果你和我一样都使用btrfs文件系统，可以利用btrfs特性来创建快照。&lt;br /&gt;
备份系统&lt;br /&gt;
&lt;code&gt;cd /&lt;/code&gt; # 回到根目录&lt;br /&gt;
&lt;code&gt;mkdir -p /mnt/.snapshots&lt;/code&gt; # 创建备份目录&lt;br /&gt;
&lt;code&gt;mount -o compress=zstd:3,subvol=/ /dev/nvme0n1p1 /mnt&lt;/code&gt; # 挂载btrfs根分区&lt;br /&gt;
&lt;code&gt;rm -rf /var/cache/portage/*&lt;/code&gt; # 清理gentoo的软件包缓存（减少快照体积）&lt;br /&gt;
&lt;code&gt;btrfs subvolume snapshot -r /mnt/@ /mnt/.snapshots/@-$(date +&quot;%Y%m%d&quot;)&lt;/code&gt; # 创建只读快照&lt;br /&gt;
&lt;code&gt;umount /mnt&lt;/code&gt; # 卸载临时挂载&lt;/p&gt;
&lt;p&gt;恢复系统&lt;br /&gt;
进入livecd环境&lt;br /&gt;
&lt;code&gt;mount -o compress=zstd:3,subvol=/ /dev/nvme0n1p1 /mnt&lt;/code&gt; # 挂载 btrfs 根分区&lt;br /&gt;
&lt;code&gt;btrfs subvolume snapshot /mnt/.snapshots/@-yyyymmdd /mnt/@-restore&lt;/code&gt; # 从快照创建临时恢复子卷&lt;br /&gt;
修改 fstab 指向临时子卷&lt;br /&gt;
&lt;code&gt;vi /etc/fstab&lt;/code&gt; # 将&quot;subvol=@&quot; 改为 &quot;subvol=@-restore&quot;&lt;br /&gt;
&lt;code&gt;cp /etc/fstab /mnt/@-restore/etc/fstab&lt;/code&gt; # 同步修改到临时子卷的fstab&lt;br /&gt;
&lt;code&gt;grub-mkconfig -o /boot/grub/grub.cfg&lt;/code&gt; # 重建 Grub 引导配置&lt;br /&gt;
&lt;code&gt;reboot&lt;/code&gt; # 重启系统&lt;br /&gt;
这样备份系统快速方便，过程不算太复杂。缺点就是只能在btrfs文件系统上这样备份。&lt;/p&gt;
&lt;p&gt;如果你格式化或迁移了硬盘，fstab的内容也要做出相应的修改。&lt;br /&gt;
重新更新引导加载程序&lt;br /&gt;
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Gentoo&lt;br /&gt;
grub-mkconfig -o /boot/grub/grub.cfg&lt;br /&gt;
重启后备份完成，这种备份方式兼容性强，支持各文件系统，就是压缩解压要花点时间。&lt;/p&gt;
&lt;p&gt;两种备份方式也可以一起使用，最后也没什么要说的了，祝你使用gentoo愉快~&lt;/p&gt;
&lt;h1&gt;参考文献&lt;/h1&gt;
&lt;p&gt;Gentoo Linux amd64 Handbook： Installing Gentoo https://wiki.gentoo.org/wiki/Handbook:AMD64/Full/Installation&lt;br /&gt;
Gentoo安装流程分享(step by step)，第一篇之基本系统的安装 https://zhuanlan.zhihu.com/p/122222365&lt;/p&gt;
</content:encoded></item></channel></rss>