Nvidia on NixOS WSL – Ollama up 24/7 on your gaming PC
在游戏 PC 上使用 NixOS WSL 运行 Nvidia 加速的 Ollama,实现 24/7 全天候可用
Nvidia on Nixos WSL - Ollama up 24/7 on your gaming PC
Posted Apr 1, 2025 Updated Apr 1, 2025 By _yomaq _ 9 min read
在家方便地使用 LLM
我一直想在我的家庭实验室里尝试使用 LLM,但又不想为了专门的 GPU 机器而增加开销,或者忍受 CPU 处理的缓慢。我还希望一切都能长期方便使用:更新需要自动化,如果操作系统崩溃,重建需要快速而简单等等。
在我的游戏 PC 上使用 WSL 运行 NixOS 似乎是完美的解决方案,但我不断遇到几个挑战:
- 担心我的 vram 被 LLM 锁定
- WSL 会自动关闭;如果你没有积极使用它,Microsoft 不支持 WSL 运行。
- WSL 上的 NixOS 不支持 Nvidia。
- 我拒绝管理一个单独的 Ubuntu 系统,因为需要从头开始重新配置。
经过几个星期的摸索,我现在解决了这些障碍:
- Ollama(默认情况下)如果模型在过去 5 分钟内未使用,则会卸载模型。
- WSL 自动启动,并保持运行。
- 为 WSL 上的 NixOS 配置了 Nvidia Container Toolkit。
- 为 NixOS 配置了 Ollama 容器。
- NixOS 处理整个系统的配置,因此从头开始重建很容易。
- 我的 NixOS flake 已经配置为自动更新,我的 WSL 系统可以直接继承这些更新。
虽然这里有一些通用的有用信息,但它主要关注 NixOS。此外,我非常依赖 Tailscale 来方便我的网络,因此也包含了一些可选的 Tailscale 步骤。
我在家积极使用的实时配置:
仅供参考
- Whole Nixos Flake
- Nvidia Module
- Ollama Container
- Open-WebUI
- Tailscale sidecar Container
- Tailscale ACL
强制 WSL 保持运行
首先,要解决最大的、与操作系统无关的问题,我找到了这个 github 帖子。假设你在 WSL 上运行 Ubuntu,你可以运行
1
```
| ```
wsl --exec dbus-launch true
```
---|---
`
这将启动 WSL 并使其保持运行。你可以在 Windows 任务计划程序中设置一个基本任务,以在“启动时”自动运行此命令,并将其设置为在用户注销后运行。
对于 WSL 上的 NixOS,我发现这不太有效,`--exec` 选项似乎存在问题。所以我改为这样设置:
1
| ```
wsl.exe dbus-launch true
---|---
`
我相信对于 NixOS,这意味着一个 shell 会在后台运行,这不如为 Ubuntu 使用 --exec
理想,但我会接受我能得到的东西。
在 WSL 上安装 NixOS
我对长期便利性的大部分要求都由 NixOS 满足。通过 NixOS 配置来配置整个系统(Nvidia、网络、容器等),可以轻松地重新部署所有内容。此外,我的 NixOS Flake 已经设置为通过 github action 进行自动每周更新,并且我所有的 NixOS 主机都配置为自动拉取并完全重建到这些更新。我的 WSL 上的 NixOS 将能够继承这些优势。
或者,如果你愿意,还有其他方法可以为你的单个 WSL 设置自动更新一次性的 NixOS 机器。
要开始安装,请按照 Nixos-WSL github 中的步骤操作:
- 如果尚未启用 WSL,请启用:
1
```
| ```
wsl--install--no-distribution
```
---|---
`
2. 从[最新版本](https://yomaq.github.io/posts/nvidia-on-nixos-wsl-ollama-up-24-7-on-your-gaming-pc/<https:/github.com/nix-community/NixOS-WSL/releases/latest>)下载 `nixos.wsl`。
3. 双击刚刚下载的文件(需要 WSL >= 2.4.4)
4. 你现在可以运行 NixOS:
1
| ```
wsl-dNixOS
---|---
`
然后将其设置为默认值
1
```
| ```
wsl --setdefault NixOS
```
---|---
`
### 基本 NixOS 配置
要配置 NixOS,请输入 WSL 并导航到 `/etc/nixos/`。你将找到一个 configuration.nix 文件,其中包含整个系统的配置,它非常简陋,我们将添加一些基本内容以使事情更容易。在第一次重建完成之前,你需要使用 Nano 编辑该文件。(我正在使用 Tailscale 进行网络连接,我推荐它,但这不是必需的。)
1 2 3 4 5 6 7 8 9
| ```
environment.systemPackages = [
pkgs.vim
pkgs.git
pkgs.tailscale
pkgs.docker
];
services.tailscale.enable = true;
wsl.useWindowsDriver = true;
nixpkgs.config.allowUnfree = true;
---|---
`
现在运行
1
```
| ```
sudo nix-channel --update
```
---|---
`
和
1
| ```
sudo nixos-rebuild switch
---|---
`
如果你正在使用 Tailscale,请登录 Tailscale,只需按照创建的链接操作即可。
1
```
| ```
sudo tailscale up
```
---|---
`
### 配置 NixOS 以使用 Nvidia Container Toolkit
目前,[Nixos on WSL](https://yomaq.github.io/posts/nvidia-on-nixos-wsl-ollama-up-24-7-on-your-gaming-pc/<https:/github.com/nix-community/NixOS-WSL?tab=readme-ov-file>) 不像标准 NixOS 那样支持 Nvidia 和 Nvidia Container Toolkit,所以我必须进行一些调整才能使其工作。
通过这些修复,Nvidia Container Toolkit 可以正常工作,你可以像预期一样与基本的 Nvidia 命令进行交互(就我所测试的而言,例如 `nvidia-smi`)。但是,依赖 Nvidia 的内置 NixOS 模块(例如 Nixos 的 `services.ollama`)不起作用。可能每个这些服务都需要自己的补丁才能正确连接到 Cuda,而且我不打算处理这些,因为仅使用容器 GPU 工作负载对我来说就足够了。
也就是说,这是使其工作的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| ```
services.xserver.videoDrivers = ["nvidia"];
hardware.nvidia.open = true;
environment.sessionVariables = {
CUDA_PATH = "${pkgs.cudatoolkit}";
EXTRA_LDFLAGS = "-L/lib -L${pkgs.linuxPackages.nvidia_x11}/lib";
EXTRA_CCFLAGS = "-I/usr/include";
LD_LIBRARY_PATH = [
"/usr/lib/wsl/lib"
"${pkgs.linuxPackages.nvidia_x11}/lib"
"${pkgs.ncurses5}/lib"
];
MESA_D3D12_DEFAULT_ADAPTER_NAME = "Nvidia";
};
hardware.nvidia-container-toolkit = {
enable = true;
mount-nvidia-executables = false;
};
systemd.services = {
nvidia-cdi-generator = {
description = "Generate nvidia cdi";
wantedBy = [ "docker.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.nvidia-docker}/bin/nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml --nvidia-ctk-path=${pkgs.nvidia-container-toolkit}/bin/nvidia-ctk";
};
};
};
virtualisation.docker = {
daemon.settings.features.cdi = true;
daemon.settings.cdi-spec-dirs = ["/etc/cdi"];
};
---|---
`
再进行一次 nixos-rebuild switch
并重新启动 WSL。现在你应该能够运行 nvidia-smi
并看到你的 GPU。你需要使用 --device=nvidia.com/gpu=all
运行所有 docker 容器以连接到 GPU。
我没有自己发现这些修复,我从这两个 github 问题中整理了这些信息:
- https://github.com/nix-community/NixOS-WSL/issues/454
- https://github.com/nix-community/NixOS-WSL/issues/578
配置 Ollama Docker 容器:
我设置了一个 Ollama 容器示例,以及一个可选的 Tailscale 容器,以使其更容易联网。如果要使用 Tailscale 容器,请取消注释所有代码,将你的 Tailscale 域名放在适当的位置,并注释掉 Ollama 容器的 port
和 networking.firewall
端口。
如果你使用 Tailscale 容器,则已使用 Tailscale Serve 进行设置,以通过签名 https 在 https://ollama.${YOUR_TAILSCALE_DOMAIN}.ts.net
上提供 Ollama API。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
```
| ```
virtualisation.oci-containers.backend = "docker";
virtualisation = {
docker = {
enable = true;
autoPrune.enable = true;
};
};
systemd.tmpfiles.rules = [
"d /var/lib/ollama 0755 root root"
#"d /var/lib/tailscale-container 0755 root root"
];
networking.firewall.allowedTCPPorts = [ 11434 ];
virtualisation.oci-containers.containers = {
"ollama" = {
image = "docker.io/ollama/ollama:latest";
autoStart = true;
environment = {
"OLLAMA_NUM_PARALLEL" = "1";
};
ports = [ 11434 ];
volumes = [ "/var/lib/ollama:/root/.ollama" ];
extraOptions = [
"--pull=always"
"--device=nvidia.com/gpu=all"
"--network=container:ollama-tailscale"
];
};
#"ollama-tailscale" = {
# image = "ghcr.io/tailscale/tailscale:latest";
# autoStart = true;
# environment = {
# "TS_HOSTNAME" = "ollama";
# "TS_STATE_DIR" = "/var/lib/tailscale";
# "TS_SERVE_CONFIG" = "config/tailscaleCfg.json";
# };
# volumes = [
# "/var/lib/tailscale-container:/var/lib"
# "/dev/net/tun:/dev/net/tun"
# "${
# (pkgs.writeTextFile {
# name = "ollamaTScfg";
# text = ''
# {
# "TCP": {
# "443": {
# "HTTPS": true
# }
# },
# "Web": {
# #replace this with YOUR tailscale domain
# "ollama.${YOUR_TAILSCALE_DOMAIN}.ts.net:443": {
# "Handlers": {
# "/": {
# "Proxy": "http://127.0.0.1:11434"
# }
# }
# }
# }
# }
# '';
# })
# }:/config/tailscaleCfg.json"
# ];
# extraOptions = [
# "--pull=always"
# "--cap-add=net_admin"
# "--cap-add=sys_module"
# "--device=/dev/net/tun:/dev/net/tun"
# ];
#};
};
```
---|---
`
再进行一次 `nixos-rebuild switch`,你的 Ollama 容器应该已启动。
### 网络和测试
如果使用 Tailscale:
* 需要先设置 Tailscale 容器,否则两个容器将继续失败。
* 执行到 Tailscale 容器中:`sudo docker exec -it ollama-tailscale sh`
* `tailscale up`
* 使用链接将其添加到你的 Tailnet
* 执行到 Ollama 容器中以拉取模型:`sudo docker exec -it ollama ollama run gemma3`
* 运行测试提示,在 WSL 上使用 `nvidia-smi` 进行验证以查看 GPU 是否正在使用。
* 从另一个 Tailscale 连接的设备测试 API:
1 2 3 4 5
| ```
curl https://ollama.${YOUR_TAILSCALE_DOMAIN}.ts.net/api/generate -d '{
"model": "gemma3",
"prompt": "test",
"stream": false
}'
---|---
`
如果不使用 Tailscale:
- 执行到 Ollama 容器中以拉取模型:
sudo docker exec -it ollama ollama run gemma3
- 运行测试提示,在 WSL 上使用
nvidia-smi
进行验证以查看 GPU 是否正在使用。 - Ollama 在 WSL 上的端口为 11434,请按照类似这样的指南通过 Windows 将其暴露给你的网络
- 摘要添加
1
2
```
| ```
"OLLAMA_HOST" = "0.0.0.0:11434";
"OLLAMA_ORIGINS" = "*";
```
---|---
`
到 NixOS 配置的 Ollama 环境。
* 使用 `ifconfig` 获取你的 WSL IP 地址,通常在 eth0 下
* 在 Windows 上,使用具有管理员权限的 Powershell 创建防火墙规则:
1 2 3
| ```
New-NetFireWallRule -DisplayName 'WSL firewall unlock' -Direction Outbound -LocalPort 11434 -Action Allow -Protocol TCP
New-NetFireWallRule -DisplayName 'WSL firewall unlock' -Direction Inbound -LocalPort 11434 -Action Allow -Protocol TCP
---|---
`
- 同样在具有管理员权限的 Windows Powershell 上:
1
```
| ```
netsh interface portproxy add v4tov4 listenport=11434 listenaddress=0.0.0.0 connectport=11434 connectaddress=$WSL-IP-ADDRESS
```
---|---
`
请务必替换 $WSL-IP-ADDRESS
* 现在使用你的 Windows LAN IP 地址,你应该能够访问 Ollama:`http://192.168.1.123:11434`
* 使用你的 Windows LAN IP 地址测试 API。
1 2 3 4 5
| ```
curl http://WINDOWS-LAN-IP:11434api/generate -d '{
"model": "gemma3",
"prompt": "test",
"stream": false
}'
---|---
`
完成!
现在你可以将你的 Ollama API 连接到你想要的任何地方,例如 Open-WebUI 等。
Homelab, Nixos nixos wsl tailscale This post is licensed under CC BY 4.0 by the author. Share