在 Steam Deck 上开启用户级别的 SMB
重要性不言而喻,远程打个补丁,从 SD 上下载点文件都非常有用,导出一些游戏也比较实用。
传统上,SMB 必须使用 Sudo 开启,但是 SteamOS 这种不可变系统有个毛病就是,每次更新完系统,之前所有的东西全部重装,包括你的 SMB,而跳过系统更新对于 SD 来说更是不可能,这点简直是跟 MC 学的,笑死。
所以一个合理的方案就是一用户级别的权限开启 SMB,这需要走一些弯路。
前置要求:HomeBrew
相比于 ArchLinux 自带的 Pacman 管理器,HB 完全安装在本地用户目录,不会被 SD 的系统更新整挂掉,所以比较方便,我们需要借助 HB 安装 SMB,安装时间比较久,运行:
brew install samba
# 检查是否安装成功
smbd -v
# 检查下安装路径
where smbd保存配置文件
cat /home/deck/env/linux/samba/deck.conf
#
# Sample configuration file for the Samba suite for Debian GNU/Linux.
#
#
# This is the main Samba configuration file. You should read the
# smb.conf(5) manual page in order to understand the options listed
# here. Samba has a huge number of configurable options most of which
# are not shown in this example
#
# Some options that are often worth tuning have been included as
# commented-out examples in this file.
# - When such options are commented with ";", the proposed setting
# differs from the default Samba behaviour
# - When commented with "#", the proposed setting is the default
# behaviour of Samba but the option is considered important
# enough to be mentioned here
#
# NOTE: Whenever you modify this file you should run the command
# "testparm" to check that you have not made any basic syntactic
# errors.
#======================= Global Settings =======================
[global]
# 将运行所需目录放到用户目录
pid directory = /home/deck/.local/var/samba/run
lock directory = /home/deck/.local/var/samba/lock
state directory = /home/deck/.local/var/samba/state
cache directory = /home/deck/.local/var/samba/cache
private dir = /home/deck/.local/var/samba/private
# 日志放到用户目录
log file = /home/deck/.local/var/log/samba/log.%m
logging = file
max log size = 1000
server role = standalone server
map to guest = bad user
# 关闭打印相关,避免依赖系统路径和权限
load printers = no
printing = bsd
printcap name = /dev/null
disable spoolss = yes
# 端口
smb ports = 1445
[deck]
path = /home/deck
browseable = yes
writable = yes
read only = no
guest ok = no
valid users = deck
create mask = 0660
directory mask = 0770
[sd]
path = /run/media/deck/deck/
browseable = yes
writable = yes
read only = no
guest ok = no
valid users = deck
create mask = 0660
directory mask = 0770NOTE
配置文件里有个坑,就是端口不能是一般的 SMB 端口,如 445,所以我在上面配置中改成了 1445,可能是权限保留问题,总之,如果是 445 端口,总是连接超时。
开启自启动
就像前面说的,开启自启动的文件最好还是放在用户目录,目录在 /home/deck/.config/systemd/user,编辑文件:
[Unit]
Description=User-level SMB Service for Deck
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/home/linuxbrew/.linuxbrew/sbin/smbd -i -d 3 -s /home/deck/env/linux/samba/deck.conf
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target保存,重载并启动配置文件:
systemctl --user daemon-reload
systemctl --user enable --now deck-smb.service接下来应该就可以放心使用了,一劳永逸。Mac 连接服务器:
smb://192.168.31.29:1445/deck配置中踩的一些坑
第一次启动报错启动太快,无法开启用户级别的 SMB:
~/.config/systemd/user > systemctl --user status smb.service
× smb.service - User-level SMB Service for Deck
Loaded: loaded (/home/deck/.config/systemd/user/smb.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Mon 2025-09-15 00:21:48 +08; 19s ago
Duration: 72ms
Invocation: 6b48f8fc4ef041bba66f33868b3b21bd
Main PID: 33601 (code=exited, status=1/FAILURE)
Sep 15 00:21:48 steamdeck systemd[1655]: smb.service: Scheduled restart job, restart counter is at 5.
Sep 15 00:21:48 steamdeck systemd[1655]: smb.service: Start request repeated too quickly.
Sep 15 00:21:48 steamdeck systemd[1655]: smb.service: Failed with result 'exit-code'.
Sep 15 00:21:48 steamdeck systemd[1655]: Failed to start User-level SMB Service for Deck.
Sep 15 00:21:55 steamdeck systemd[1655]: smb.service: Start request repeated too quickly.
Sep 15 00:21:55 steamdeck systemd[1655]: smb.service: Failed with result 'exit-code'.
Sep 15 00:21:55 steamdeck systemd[1655]: Failed to start User-level SMB Service for Deck.当时在前台运行没有问题,一旦用 systemctl 就报错,查看日志发现:
journalctl --user -u smb.service -e --no-pager
Sep 16 00:05:27 steamdeck systemd[1655]: Started User-level SMB Service for Deck.
Sep 16 00:05:27 steamdeck systemd[1655]: smb.service: Main process exited, code=exited, status=1/FAILURE
Sep 16 00:05:27 steamdeck systemd[1655]: smb.service: Failed with result 'exit-code'.
Sep 16 00:05:27 steamdeck systemd[1655]: smb.service: Scheduled restart job, restart counter is at 1.
Sep 16 00:05:27 steamdeck systemd[1655]: Started User-level SMB Service for Deck.
Sep 16 00:05:27 steamdeck systemd[1655]: smb.service: Main process exited, code=exited, status=1/FAILURE
Sep 16 00:05:27 steamdeck systemd[1655]: smb.service: Failed with result 'exit-code'.
Sep 16 00:05:27 steamdeck systemd[1655]: smb.service: Scheduled restart job, restart counter is at 2.
Sep 16 00:05:27 steamdeck systemd[1655]: Started User-level SMB Service for Deck.
Sep 16 00:05:27 steamdeck systemd[1655]: smb.service: Main process exited, code=exited, status=1/FAILURE
Sep 16 00:05:27 steamdeck systemd[1655]: smb.service: Failed with result 'exit-code'.
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Scheduled restart job, restart counter is at 3.
Sep 16 00:05:28 steamdeck systemd[1655]: Started User-level SMB Service for Deck.
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Main process exited, code=exited, status=1/FAILURE
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Failed with result 'exit-code'.
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Scheduled restart job, restart counter is at 4.
Sep 16 00:05:28 steamdeck systemd[1655]: Started User-level SMB Service for Deck.
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Main process exited, code=exited, status=1/FAILURE
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Failed with result 'exit-code'.
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Scheduled restart job, restart counter is at 5.
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Start request repeated too quickly.
Sep 16 00:05:28 steamdeck systemd[1655]: smb.service: Failed with result 'exit-code'.
Sep 16 00:05:28 steamdeck systemd[1655]: Failed to start User-level SMB Service for Deck.连续重启了 5 次然后报错,怀疑是用户权限目录不足,所以创建用户目录,加上手动指定输出日志目录
# 把 Samba 的运行/锁/状态/缓存/私有/日志目录放到用户目录,上面配置已体现
pid directory = /home/deck/.local/var/samba/run
lock directory = /home/deck/.local/var/samba/lock
state directory = /home/deck/.local/var/samba/state
cache directory = /home/deck/.local/var/samba/cache
private dir = /home/deck/.local/var/samba/private
log file = /home/deck/.local/var/log/samba/log.%m
log level = 2
server role = standalone server
security = user然后发现好像不是这个的问题,排查可能是 SMBD 绑定端口(445)的问题,赋权:
# 一次性给 smbd 设置能力(需要 sudo):
# sudo setcap 'cap_net_bind_service=+ep' /home/linuxbrew/.linuxbrew/sbin/smbd
# Invalid file '/home/linuxbrew/.linuxbrew/sbin/smbd' for capability operation
# 目标不是“普通文件”。Homebrew 前缀下的 smbd 通常是个符号链接,setcap 不会对符号链接生效,必须对真实二进制文件本体设置能力
realbin="$(readlink -f /home/linuxbrew/.linuxbrew/opt/samba/sbin/smbd)"
echo "$realbin"
file "$realbin" # 确认是 ELF 可执行
sudo setcap 'cap_net_bind_service=+ep' "$realbin"
getcap "$realbin" # 验证已生效最后发现还是不行,没办法了,直接前台调试看看:
/home/linuxbrew/.linuxbrew/sbin/smbd -i -d 3 -s /home/deck/env/linux/samba/deck.conf
# `-i`:前台运行(不 daemonize)
# `-d 3`:日志等级为 3(可调高到 5 甚至 10,越高越详细)
# `-s ...`:指定你的配置文件然后发现了报错
/home/linuxbrew/.linuxbrew/sbin/smbd -i -d 3 -s /home/deck/env/linux/samba/deck.conf
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
added interface wlan0 ip=192.168.31.29 bcast=192.168.31.255 netmask=255.255.255.0
smbd version 4.22.4 started.
Copyright Andrew Tridgell and the Samba Team 1992-2025
uid=1000 gid=1000 euid=1000 egid=1000
directory_create_or_exist: mkdir failed on directory /home/deck/.local/var/samba/private/msg.sock: No such file or directorySamba 4.x 需要 private dir 下有 msg.sock 目录用于进程间通信。之前可能只在 systemd 单元里只创建了 /home/deck/.local/var/samba/private,但没有递归创建 msg.sock 子目录。
mkdir -p /home/deck/.local/var/samba/private/msg.sock再次前台启动:
/home/linuxbrew/.linuxbrew/sbin/smbd -i -d 3 -s /home/deck/env/linux/samba/deck.conf
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
added interface wlan0 ip=192.168.31.29 bcast=192.168.31.255 netmask=255.255.255.0
smbd version 4.22.4 started.
Copyright Andrew Tridgell and the Samba Team 1992-2025
uid=1000 gid=1000 euid=1000 egid=1000
invalid permissions on directory '/home/deck/.local/var/samba/private/msg.sock': has 0755 should be 0700发现权限不对,这是 Samba 的安全检查,要求 msg.sock 目录权限必须是 0700(只有所有者可读写执行),而你现在是 0755(其他用户也可读/执行),修正权限
chmod 700 /home/deck/.local/var/samba/private/msg.sock然后再次启动,虽然成功启动了 waiting for connections,但似乎仍然有报错:
/home/linuxbrew/.linuxbrew/sbin/smbd -i -d 3 -s /home/deck/env/linux/samba/deck.conf
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
added interface wlan0 ip=192.168.31.29 bcast=192.168.31.255 netmask=255.255.255.0
smbd version 4.22.4 started.
Copyright Andrew Tridgell and the Samba Team 1992-2025
uid=1000 gid=1000 euid=1000 egid=1000
Registered MSG_REQ_DMALLOC_MARK and LOG_CHANGED
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
Processing section "[deck]"
adding IPC service
added interface wlan0 ip=192.168.31.29 bcast=192.168.31.255 netmask=255.255.255.0
loaded services
set_profile_level: INFO: Profiling support unavailable in this build.
daemon 'smbd' : Starting process ...
tdb(/home/deck/.local/var/samba/state/registry.tdb): tdb_open_ex: could not open file /home/deck/.local/var/samba/state/registry.tdb: No such file or directory
Could not open tdb: No such file or directory
Failed to fetch domain sid for WORKGROUP
tdb(/home/deck/.local/var/samba/state/account_policy.tdb): tdb_open_ex: could not open file /home/deck/.local/var/samba/state/account_policy.tdb: No such file or directory
Could not open tdb: No such file or directory
account_policy_get: tdb_fetch_uint32_t failed for type 1 (min password length), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 2 (password history), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 3 (user must logon to change password), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 4 (maximum password age), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 5 (minimum password age), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 6 (lockout duration), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 7 (reset count minutes), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 8 (bad lockout attempt), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 9 (disconnect time), returning 0
account_policy_get: tdb_fetch_uint32_t failed for type 10 (refuse machine password change), returning 0
tdbsam_open: Converting version 0.0 database to version 4.0.
tdbsam_convert_backup: updated /home/deck/.local/var/samba/private/passdb.tdb file.
tdb(/home/deck/.local/var/samba/state/winbindd_idmap.tdb): tdb_open_ex: could not open file /home/deck/.local/var/samba/state/winbindd_idmap.tdb: No such file or directory
TDBSAM converted successfully.
waiting for connections启动之后,我的 Mac 连接服务器 smb://192.168.31.29 仍然报错找不到,非常奇怪。排查了端口,服务等等,最终发现是端口的问题,换一个端口就能连上。
# 1. 检查 smbd 是否监听 445 端口(Mac 只用 445,不用 139)
ss -ltnp | grep 445
netstat -anp | grep 445
# 应该看到 0.0.0.0:445 或 192.168.31.29:445 有 smbd 进程。
LISTEN 0 50 0.0.0.0:445 0.0.0.0:*
LISTEN 0 50 [::]:445 [::]:*
# 2. 检查防火墙(如 firewalld、iptables)是否放行 445 端口:
sudo iptables -L -n | grep 445
sudo ufw status
# 3. smbd 没有绑定 445 端口(权限问题),确定执行过
sudo setcap 'cap_net_bind_service=+ep' /home/linuxbrew/.linuxbrew/opt/samba/sbin/smbd
# 4. 配置问题,你的配置没问题,[deck] 共享已开放,valid users = deck,Mac 端要用 deck 用户和密码连接,确认你已设置 Samba 密码:
sudo /home/linuxbrew/.linuxbrew/bin/smbpasswd -L -c /home/deck/env/linux/samba/deck.conf -a deck一顿操作下来什么都没成功,然后 Mac 连接的时候还是迅速报错:
smbutil view //[email protected]/deck
smbutil: server connection failed: Operation timed out观察 Deck 的前台命令行,无任何连接输出
~/env > /home/linuxbrew/.linuxbrew/sbin/smbd -i -d 3 -s /home/deck/env/linux/samba/deck.conf
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
added interface wlan0 ip=192.168.31.29 bcast=192.168.31.255 netmask=255.255.255.0
smbd version 4.22.4 started.
Copyright Andrew Tridgell and the Samba Team 1992-2025
uid=1000 gid=1000 euid=1000 egid=1000
Registered MSG_REQ_DMALLOC_MARK and LOG_CHANGED
lp_load_ex: refreshing parameters
Initialising global parameters
Processing section "[global]"
Processing section "[deck]"
adding IPC service
added interface wlan0 ip=192.168.31.29 bcast=192.168.31.255 netmask=255.255.255.0
loaded services
set_profile_level: INFO: Profiling support unavailable in this build.
daemon 'smbd' : Starting process ...
Failed to fetch domain sid for WORKGROUP
waiting for connections表现是可以 Ping 通 Steam Deck ,但是 NC 连不上
~ > ping 192.168.31.29
PING 192.168.31.29 (192.168.31.29): 56 data bytes
64 bytes from 192.168.31.29: icmp_seq=0 ttl=64 time=11.890 ms
64 bytes from 192.168.31.29: icmp_seq=1 ttl=64 time=4.102 ms
q64 bytes from 192.168.31.29: icmp_seq=2 ttl=64 time=39.757 ms
64 bytes from 192.168.31.29: icmp_seq=3 ttl=64 time=4.115 ms
^C
--- 192.168.31.29 ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 4.102/14.966/39.757/14.661 ms
~ > nc -vz 192.168.31.29 445
nc: connectx to 192.168.31.29 port 445 (tcp) failed: Connection refused说明网络互通,Mac 能到达 Deck。而 Deck 上 445 端口虽然 smbd 启动时监听,但实际上没有真正开放,或者监听的 smbd 进程已退出/崩溃,或者被别的服务占用后立刻关闭。
怀疑是谁占了 445 端口,查了一下
~/env > ps aux | grep smbd
deck 81179 0.0 0.1 84572 26232 pts/5 S+ 20:53 0:00 /home/linuxbrew/.linuxbrew/sbin/smbd -i -d 3 -s /home/deck/env/linux/samba/deck.conf
deck 82238 0.0 0.0 6596 4472 pts/7 S+ 20:59 0:00 grep --color=auto smbd
~/env > ss -ltnp | grep 445
LISTEN 0 50 0.0.0.0:445 0.0.0.0:*
LISTEN 0 50 [::]:445 [::]:*
~/env > sudo lsof -i :445
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
smbd 81179 deck 30u IPv6 4205857 0t0 TCP *:microsoft-ds (LISTEN)
smbd 81179 deck 32u IPv4 4205859 0t0 TCP *:microsoft-ds (LISTEN)发现谁都没占 445。实在没招了,问了下 chatGPT
这种情况99% 是 Linux 内核拒绝了 445 端口的非 root 绑定,即使你看到
ss -ltnp显示监听,实际上内核会直接拒绝外部连接。
- 普通用户运行的 smbd,虽然 setcap 后能监听 445,但部分 Linux 发行版(包括 SteamOS/Arch 衍生)默认限制非 root 进程监听 445/139,或 setcap 没有生效。
- 这会导致:本地能看到监听,但所有外部连接都被内核直接拒绝,smbd 根本收不到连接,表现为“Connection refused”。
没招了,之前的步骤全部用 ROOT 操作一遍,然后启动这个服务,我发现仍然无法连接。具体的命令就不罗列了,太折腾了,最后试了一下 1445 端口,成功了。
简直了。