You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nix环境下Nim构建的Nitter无法加载SSL证书求助

在NixOS上运行Nitter时遇到CA证书加载失败导致的速率限制问题

我在NixOS 22.05上运行Nitter包时触发速率限制错误,尝试基于Git最新版本构建后问题依旧,错误日志如下:

Starting Nitter
Starting Nitter at http://mymachine
Connected to Redis at localhost:7777
fetching token failed: No SSL/TLS CA certificates found.
RateLimitError: rate limited

排查后确认核心问题是Nim无法加载CA证书,即使已添加cacert和openssl包,容器内也能看到/etc/ssl/certs/ca-bundle.crt存在,但Nitter仍无法识别。


相关配置文件

构建配置 services/nitter.nix

{ pkgs, lib, nimPackages, fetchFromGitHub, ... }:
with pkgs;
let

  nitter-git = nimPackages.buildNimPackage {
  pname = "nitter";
  version = "unstable-2022-10-17";
 
  src = fetchFromGitHub {
    owner = "zedeus";
    repo = "nitter";
    rev = "2ac3afa5b273a502d7632e9346c7c3bc9283fb48";
    hash = "sha256-fdzVfzmEFIej6Kb/K9MQyvbN8aN3hO7RetHL53cD59k=";
  };
 
  buildInputs = with nimPackages; [
    flatty
    jester
    jsony
    karax
    markdown
    nimcrypto
    packedjson
    redis
    redpool
    sass
    supersnappy
    zippy
  ];
 
  nimBinOnly = true;

  nimFlags = ["-d:ssl"];
 
  postBuild = ''
    nim c --hint[Processing]:off -r tools/gencss
    nim c --hint[Processing]:off -r tools/rendermd
  '';
 
  postInstall = ''
    mkdir -p $out/share/nitter
    cp -r public $out/share/nitter/public
  '';
 
  meta = with lib; {
    homepage = "https://github.com/zedeus/nitter";
    description = "Alternative Twitter front-end";
    license = licenses.agpl3Only;
    maintainers = with maintainers; [ erdnaxe ];
    mainProgram = "nitter";
  };
};

  redis-run = writeTextFile {
      name = "redis-run";
      executable = true;
      destination = "/etc/s6/redis/run";
      text = ''
      #!/bin/sh
      echo "Starting Redis on 7777"
      exec redis-server --port 7777
      '';
  };
  redis-finish = writeTextFile {
      name = "redis-finish";
      executable = true;
      destination = "/etc/s6/redis/finish";
      text = ''
      #!/bin/sh
      echo "Stopping Redis"
      '';
  };
  nitter-run = writeTextFile {
      name = "nitter-run";
      executable = true;
      destination = "/etc/s6/nitter/run";
      text = ''
      #!/bin/sh
      echo "Starting Nitter"
      exec nitter
      '';
  };
  nitter-finish = writeTextFile {
      name = "nitter-finish";
      executable = true;
      destination = "/etc/s6/nitter/finish";
      text = ''
      #!/bin/sh
      echo "Stopping Nitter"
      '';
  };
  nitter-conf = writeTextFile {
      name = "nitter-conf";
      executable = true;
      destination = "/etc/nitter.conf";
      text = ''
        [Server]
        address = "0.0.0.0"
        port = 8182
        https = false  # disable to enable cookies when not using https
        httpMaxConnections = 100
        staticDir = "/share/nitter/public"
        title = "nitter"
        hostname = "myhost"

        [Cache]
        listMinutes = 240  # how long to cache list info (not the tweets, so keep it high)
        rssMinutes = 10  # how long to cache rss queries
        redisHost = "localhost"  # Change to "nitter-redis" if using docker-compose
        redisPort = 7777
        redisPassword = ""
        redisConnections = 20  # connection pool size
        redisMaxConnections = 30
        # max, new connections are opened when none are available, but if the pool size
        # goes above this, they're closed when released. don't worry about this unless
        # you receive tons of requests per second

        [Config]
        hmacKey = "somereallylongrandomkeyhere"  # random key for cryptographic signing of video urls
        base64Media = false  # use base64 encoding for proxied media urls
        enableRSS = true  # set this to false to disable RSS feeds
        enableDebug = false  # enable request logs and debug endpoints
        proxy = ""  # http/https url, SOCKS proxies are not supported
        proxyAuth = ""
        tokenCount = 10
        # minimum amount of usable tokens. tokens are used to authorize API requests,
        # but they expire after ~1 hour, and have a limit of 187 requests.
        # the limit gets reset every 15 minutes, and the pool is filled up so there's
        # always at least $tokenCount usable tokens. again, only increase this if
        # you receive major bursts all the time

        # Change default preferences here, see src/prefs_impl.nim for a complete list
        [Preferences]
        theme = "Nitter"
        replaceTwitter = ""
        replaceYouTube = "piped.kavin.rocks"
        replaceReddit = "teddit.net"
        replaceInstagram = ""
        proxyVideos = true
        hlsPlayback = false
        infiniteScroll = false
      '';
  };
in
  dockerTools.buildLayeredImage {
    name = "nitter";
    contents = [ nitter-git s6 redis git busybox cacert openssl
                 redis-run redis-finish nitter-run nitter-finish
                 nitter-conf ];
    config = {
      Entrypoint = [ "/bin/s6-svscan" "/etc/s6" ];
      Env = [ "NITTER_CONF_FILE=/etc/nitter.conf" ];
      Volumes = {};
    };
  }

调用配置 services.nix

let
  config = import ./config.nix;
  pkgs = config.pkgs;
  nitter = import ./services/nitter.nix;
in rec {
  serviceimages = pkgs.writeText "images.ini" ''
    nitter=${nitter(pkgs)}
  '';
}

NixOS版本配置 config.nix

{
  # nixos-22.05
  pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/8de8b98839d1f20089582cfe1a81207258fcc1f1.tar.gz") {};
}

解决方法

Nim的SSL库在NixOS容器环境下无法自动识别CA证书路径,可通过以下两种方式修复:

1. 运行时添加环境变量

修改dockerTools.buildLayeredImage的Env配置,指定CA证书路径:

config = {
  Entrypoint = [ "/bin/s6-svscan" "/etc/s6" ];
  Env = [ 
    "NITTER_CONF_FILE=/etc/nitter.conf"
    "SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
  ];
  Volumes = {};
};

2. 编译时强制指定CA证书路径(可选)

如果运行时环境变量不生效,可在构建Nitter时通过nimFlags添加证书路径定义:

nimFlags = [
  "-d:ssl"
  "-d:sslCAFile=/etc/ssl/certs/ca-bundle.crt"
];

验证修复

重新构建镜像并运行,fetching token failed: No SSL/TLS CA certificates found.错误会消失,Nitter可正常获取API令牌,速率限制问题也会随之解决。


内容的提问来源于stack exchange,提问作者djsumdog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:55:27