前言

我承认我是一个喜欢反复无意义折腾的人,每隔一段时间,我的archlinux就如同新机一般干净。但电脑终究还是要在一个稳定的环境下拿来工作的。所以我还是放弃arch, 当然,也没有回到windows, 而是叛变到了nixos。

nixos吸引我的地方就是它的可复现性,我可以随便折腾我的系统也不会崩,也不会忘记到底安装了些什么包,一切都是可控的。

nixos能做到这一点,都归功于他的函数式系统配置方式,就像是rust的cargo、java的maven、python的uv一样,要安装什么包,就可以写在配置文件中,编辑完成后,一个重载命令即可一键复现系统。

nixos配置记录

待更新

flatpak

建议GUI软件全部用flatpak下载(除了clash-verge这种要改系统配置的,或者浏览器这种新机器必不可少的,或者steam,以及qq和wechat这种flatpak安装的不会看系统字体的),尤其是有中文输入需求的软件,可以少很多心智负担。

flatpak常用命令

flatpak search <id或名称>

flatpak install <id或名称>

flatpak uninstall <id或名称>

flatpak list

vscode

先说一下,建议不要考虑用nix的方法配置vscode。

有这功夫拿nix配置vscode,不如去配置neovim。

这里详细讲一下vscode的配置。

当你用flatpak安装vscode后,会发现终端和系统终端隔离。例如我在configuration.nix里配置了nodejs,但是vscode的终端却用不了。

有两个解决方案:

  1. 在flatpak里也下载环境。
  2. 把vscode的终端修改为系统的终端。

方案一就不说了,search一下安装就好了(我不希望一个list下来一堆都是系统环境)。

方案二怎么实现呢。

其实当你第一次用flatpak下载并打开了vscode后,自动跳出来的文件已经告诉了你这个答案:


https://www.flathub.org

------------------------------------------------------------------------------------
| Warning: You are running an unofficial Flatpak version of Visual Studio Code !!! |
------------------------------------------------------------------------------------

Please open issues under: https://github.com/flathub/com.visualstudio.code/issues


This version is running inside a container and is therefore not able
to access SDKs on your host system!

To execute commands on the host system, run inside the sandbox:

  $ host-spawn <COMMAND>
  
To make the Integrated Terminal automatically use the host system's shell,
you can add this to your profile settings:

{
  "terminal.integrated.defaultProfile.linux": "bash",
  "terminal.integrated.profiles.linux": {
    "bash": {
      "path": "host-spawn",
      "args": ["bash"]
    }
  }
}

This Flatpak provides a standard development environment (gcc, python, etc).
To see what's available:

  $ flatpak run --command=sh com.visualstudio.code
  $ ls /usr/bin (shared runtime)
  $ ls /app/bin (bundled with this flatpak)

To get support for additional languages or tools within the Flatpak, you have to install SDK extensions, e.g.

  $ flatpak install flathub org.freedesktop.Sdk.Extension.dotnet
  $ flatpak install flathub org.freedesktop.Sdk.Extension.golang
  $ FLATPAK_ENABLE_SDK_EXT=dotnet,golang flatpak run com.visualstudio.code

Similarly for shells and other tools:

  $ flatpak install com.visualstudio.code.tool.fish
  $ flatpak install com.visualstudio.code.tool.podman

You can use

  $ flatpak search <TEXT>

to find others.

重点就在这里:

{
  "terminal.integrated.defaultProfile.linux": "bash",
  "terminal.integrated.profiles.linux": {
    "bash": {
      "path": "host-spawn",
      "args": ["bash"]
    }
  }
}

首先打开设置,在搜索设置里面输入 terminal.integrated.profiles.linux。接着点击 在settings.json里编辑

{
    "workbench.colorTheme": "Dracula Theme",
    "terminal.integrated.defaultProfile.linux": "fish",
    "terminal.integrated.profiles.linux": {
        "bash": {
            "path": "host-spawn",
            "args": ["bash"]
        },
        "zsh": {
            "path": "zsh"
        },
        "fish": {
            "path": "host-spawn",
            "args": ["fish"]
        },
        "tmux": {
            "path": "tmux",
            "icon": "terminal-tmux"
        },
        "pwsh": {
            "path": "pwsh",
            "icon": "terminal-powershell"
        }
    }
}

这结构就一目了然了。

添加一个 "terminal.integrated.defaultProfile.linux": "fish",

这样默认打开的就是fish,如果你用zsh也是一样的。

再修改 fish(看你用的是哪个)的path和args。

图片-svlB.png

完美

开发环境

nix develop

当我在使用 pythonopencv-python时,发现图像不能正常显示,而是会抛出如下错误:

File "main.py", line 1, in <module>
    import cv2
  File "/home/binigo/python/test/.venv/lib/python3.8/site-packages/cv2/__init__.py", line 181, in <module>
    bootstrap()
  File "/home/binigo/python/test/.venv/lib/python3.8/site-packages/cv2/__init__.py", line 153, in bootstrap
    native_module = importlib.import_module("cv2")
  File "/home/binigo/.local/share/uv/python/cpython-3.8.20-linux-x86_64-gnu/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
ImportError: libGL.so.1: cannot open shared object file: No such file or directory

libGl.so.1应该是一个正常的,有图形化界面的linux发行版都会安装的。但是由于nixos的特殊性质,原本应该放在 /usr/lib/里的的东西以及所有你会安装的东西都在 /nix/store里统一管理,不会按照常规发行版来。

而nixos的开发方式虽有一丝繁琐,但依然遵循nix的高可复现性理念。

和nixos的configuration.nix一样,你可以在你的工作目录下,新建一个 flake.nix

然后输入:

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
    utils.url = "github:numtide/flake-utils";
  };
  outputs = { self, nixpkgs, utils }: utils.lib.eachDefaultSystem (system:
    let
      pkgs = nixpkgs.legacyPackages.${system};
    in
    {
      devShell = pkgs.mkShell rec {
        buildInputs = with pkgs; [
          libGLU libGL
          xorg.libxcb
          glib
          uv
          libz
          xorg.libX11
          xorg.libSM
          xorg.libICE
          xorg.libXext
          qt5.qtbase
        ];

        LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;
  
        # shellHook = ''
        #   export XDG_RUNTIME_DIR=/tmp/runtime-root
        #   mkdir -p $XDG_RUNTIME_DIR
  
        # '';
      };
    }
  );
}

其中 buildInput中的一大堆就是我们需要的依赖库,一样是需要什么导什么,然后再设置 LD_LIBRARY_PATH来让该环境下的程序可以识别到对应的lib依赖。

然后在你的工作目录下输入命令:

 nix develop --extra-experimental-features "nix-command flakes"

现在你在新的终端里输入程序执行命令,使用的依赖就是在flake.nix中所写的依赖了。

那么要怎么知道自己该导入什么包呢?

根据你的程序报错信息来。

libGL.so.1就导入libGL。

但是后续,opencv又报了额外的错误:

qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/home/binigo/python/awa/.venv/lib/python3.13/site-packages/cv2/qt/plugins" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: xcb.

大概是qt的插件缺依赖,而我尝试导入 xorg.libxcb,依然没有作用,怎么办呢?

在和ai斗智斗勇良久之后,gemini终于告诉了我一个靠谱的答案。

ldd .venv/lib/python3.13/site-packages/cv2/qt/plugins/platforms/libqxcb.so

这样就能直接找到缺的库,然后再去NixOS Search - Packages这里安装对应的包就好了。

另外,不知道 LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;能不能写道环境配置中,没试过,不知道有什么后果。