From 234f4354f9dc81629ced2a590b47c070893d42df Mon Sep 17 00:00:00 2001 From: yuta Date: Thu, 23 Jul 2026 15:08:03 +0900 Subject: [PATCH] feat: add NixOS service module --- README.md | 32 ++++++++++++++++ flake.nix | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 388603a..14c07dd 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,38 @@ Development binds to `127.0.0.1` by default. `dev:tailscale` binds to only on a trusted network and obtain the Tailscale address with `tailscale ip -4`. +## NixOS service + +The flake provides both a production package and a NixOS module. Import the +module and configure the relay: + +```nix +{ + inputs.twitter-lite.url = + "git+https://git.yutakobayashi.com/yuta/twitter-lite"; + + outputs = { nixpkgs, twitter-lite, ... }: { + nixosConfigurations.example = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + twitter-lite.nixosModules.default + { + services.twitter-lite = { + enable = true; + relayBaseUrl = "http://127.0.0.1:6900"; + # profileName = "default"; + }; + } + ]; + }; + }; +} +``` + +The service listens on `127.0.0.1:3000` by default. Set +`services.twitter-lite.host` or `services.twitter-lite.port` to change the +listener. The package can also be built directly with `nix build`. + ## Reliability Bird uses X's internal GraphQL operations through the configured relay. Query diff --git a/flake.nix b/flake.nix index 5ef1c04..294d3e7 100644 --- a/flake.nix +++ b/flake.nix @@ -3,11 +3,57 @@ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - outputs = { nixpkgs, ... }: + outputs = { self, nixpkgs, ... }: let systems = [ "x86_64-linux" "aarch64-linux" ]; forAllSystems = nixpkgs.lib.genAttrs systems; + mkTwitterLite = pkgs: + pkgs.stdenvNoCC.mkDerivation (finalAttrs: { + pname = "twitter-lite"; + version = "0.0.0"; + src = self; + + pnpmDeps = pkgs.fetchPnpmDeps { + inherit (finalAttrs) pname version src; + pnpm = pkgs.pnpm_11; + fetcherVersion = 4; + hash = "sha256-Dk0GkHhvVuls8CkBxYmKV4xYCaZ4vR1UDYCgQmHMgaM="; + }; + + nativeBuildInputs = with pkgs; [ + makeWrapper + nodejs_22 + pnpm_11 + pnpmConfigHook + ]; + + buildPhase = '' + runHook preBuild + pnpm build + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + mkdir -p $out/lib/twitter-lite + cp -r .output/. $out/lib/twitter-lite/ + makeWrapper ${nixpkgs.lib.getExe pkgs.nodejs_22} $out/bin/twitter-lite \ + --add-flags "$out/lib/twitter-lite/server/index.mjs" + runHook postInstall + ''; + + meta.mainProgram = "twitter-lite"; + }); in { + packages = forAllSystems (system: + let + pkgs = import nixpkgs { inherit system; }; + twitter-lite = mkTwitterLite pkgs; + in { + inherit twitter-lite; + default = twitter-lite; + }); + devShells = forAllSystems (system: let pkgs = import nixpkgs { inherit system; }; in { @@ -18,5 +64,65 @@ "${pkgs.chromium}/bin/chromium"; }; }); + + nixosModules.default = { config, lib, pkgs, ... }: + let cfg = config.services.twitter-lite; + in { + options.services.twitter-lite = { + enable = lib.mkEnableOption "Twitter Lite"; + + package = lib.mkOption { + type = lib.types.package; + default = mkTwitterLite pkgs; + defaultText = lib.literalExpression "twitter-lite.packages.\${pkgs.system}.default"; + description = "Twitter Lite package to run."; + }; + + relayBaseUrl = lib.mkOption { + type = lib.types.nonEmptyStr; + example = "http://127.0.0.1:6900"; + description = "Base URL of the Twitter relay."; + }; + + profileName = lib.mkOption { + type = lib.types.nullOr lib.types.nonEmptyStr; + default = null; + example = "default"; + description = "Relay profile to use when the relay has multiple profiles."; + }; + + host = lib.mkOption { + type = lib.types.nonEmptyStr; + default = "127.0.0.1"; + description = "Address on which Twitter Lite listens."; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 3000; + description = "Port on which Twitter Lite listens."; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.twitter-lite = { + description = "Twitter Lite"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + environment = { + HOST = cfg.host; + PORT = toString cfg.port; + TWITTER_RELAY_BASE_URL = cfg.relayBaseUrl; + } // lib.optionalAttrs (cfg.profileName != null) { + BIRD_PROFILE_NAME = cfg.profileName; + }; + serviceConfig = { + DynamicUser = true; + ExecStart = lib.getExe cfg.package; + Restart = "on-failure"; + }; + }; + }; + }; }; }