diff --git a/flake.nix b/flake.nix index e372404..26edc5e 100644 --- a/flake.nix +++ b/flake.nix @@ -102,6 +102,7 @@ overlay-local = final: prev: { codex = prev.callPackage ./pkgs/codex/package.nix { }; + opencode = prev.callPackage ./pkgs/opencode/package.nix { }; beads = let bdBase = diff --git a/hosts/liminal/configuration.nix b/hosts/liminal/configuration.nix index 7fe3d4a..de7d9c9 100644 --- a/hosts/liminal/configuration.nix +++ b/hosts/liminal/configuration.nix @@ -104,6 +104,9 @@ security.sudo.extraConfig = '' # Don't lecture after reboot Defaults lecture = never + + # Let hunner run commands as the agents user without a password. + hunner ALL=(agents) NOPASSWD: ALL ''; # Add local development CA security.pki.certificates = [ @@ -275,6 +278,13 @@ just socat pkgs.beads + gh + pkgs.opencode + python3 + clang + clangStdenv + cmake + just ]; }; users.users.hunner = { @@ -284,6 +294,41 @@ hashedPasswordFile = config.sops.secrets.hashedPassword.path; shell = pkgs.zsh; packages = with pkgs; [ + alacritty + rofi + wofi + xss-lock + xlockmore + dzen2 + arandr + xclip + scrot + xorg.xrandr + xorg.xsetroot + xorg.xset + xorg.xev + hsetroot + redshift + pkgs.unstable.code-cursor + pkgs.unstable.cursor-cli + pwvucontrol + pamixer + helvum + #hp15c + #nonpareil + kitty # for Hyprland + kdePackages.dolphin # file browser in hyprland + cliphist + xscreensaver + scarlett2 + alsa-scarlett-gui + #pkgs.unstable.ndi-6 + #(pkgs.unstable.flameshot.override { enableWlrSupport = true; }) + hyprshot + hyprpicker + flameshot + chromium + lmstudio fzf neovim asdf-vm @@ -348,6 +393,7 @@ sops bitwarden-desktop bitwarden-cli + itch ]; }; systemd.user.services = { @@ -381,7 +427,13 @@ nixpkgs.config.allowUnfree = true; # Allow dynamic linked binaries - programs.nix-ld.enable = true; + programs.nix-ld = { + enable = true; + libraries = with pkgs; [ + stdenv.cc.cc.lib + ]; + }; + programs.steam = { enable = true; @@ -406,52 +458,18 @@ file ripgrep powertop - alacritty - rofi - wofi - xss-lock - xlockmore fortune - dzen2 - arandr - xclip shellcheck - scrot fd - xorg.xrandr - xorg.xsetroot - xorg.xset - xorg.xev - hsetroot - redshift - pkgs.unstable.code-cursor - pkgs.unstable.cursor-cli - pwvucontrol - pamixer - helvum - #hp15c - #nonpareil framework-tool - kitty # for Hyprland - kdePackages.dolphin # file browser in hyprland - cliphist restic - xscreensaver unzip zip - scarlett2 - alsa-scarlett-gui - #pkgs.unstable.ndi-6 xdg-utils btrbk devenv lsof - #(pkgs.unstable.flameshot.override { enableWlrSupport = true; }) - hyprshot - hyprpicker - flameshot - chromium - lmstudio + sg3_utils ]; services.clipmenu.enable = true; @@ -516,8 +534,8 @@ # services.openssh.enable = true; # Open ports in the firewall. - networking.firewall.allowedTCPPorts = [ 8080 8081 8082 1234 ]; - networking.firewall.allowedUDPPorts = [ 8080 8081 8082 1234 ]; + networking.firewall.allowedTCPPorts = [ 8080 8081 8082 1234 4096 4747 ]; + networking.firewall.allowedUDPPorts = [ 8080 8081 8082 1234 4096 4747 ]; # Or disable the firewall altogether. # networking.firewall.enable = false; systemd.services.upower.enable = true; diff --git a/hosts/ruil/configuration.nix b/hosts/ruil/configuration.nix index b1ed5f1..046d857 100644 --- a/hosts/ruil/configuration.nix +++ b/hosts/ruil/configuration.nix @@ -34,7 +34,7 @@ mode = "0400"; }; - # HTTPS certificates for `s.hunner.dev` (works with Cloudflare Full strict). + # HTTPS certificates for `search.hunner.dev` (works with Cloudflare Full strict). security.acme = { acceptTerms = true; defaults.email = "me@hunner.dev"; @@ -124,15 +124,15 @@ enable = true; configureNginx = true; redisCreateLocally = true; - domain = "s.hunner.dev"; + domain = "search.hunner.dev"; environmentFile = config.sops.secrets.searx-env.path; settings.server.secret_key = "$SEARX_SECRET_KEY"; settings.server.limiter = true; - settings.server.base_url = lib.mkForce "https://s.hunner.dev/"; + settings.server.base_url = lib.mkForce "https://search.hunner.dev/"; settings.general.open_metrics = "$SEARX_METRICS_PASSWORD"; }; - services.nginx.virtualHosts."s.hunner.dev" = { + services.nginx.virtualHosts."search.hunner.dev" = { enableACME = true; forceSSL = true; @@ -169,11 +169,11 @@ }; }; - # Catch-all vhost so only s.hunner.dev serves SearXNG. + # Catch-all vhost so only search.hunner.dev serves SearXNG. services.nginx.virtualHosts."_" = { default = true; addSSL = true; - useACMEHost = "s.hunner.dev"; + useACMEHost = "search.hunner.dev"; locations."/" = { return = "200 \"This page intentionally left blank.\""; extraConfig = '' diff --git a/justfile b/justfile index 764d60d..fbda24b 100644 --- a/justfile +++ b/justfile @@ -32,6 +32,9 @@ deploy-liminal: deploy-zima: just deploy-auto zima root@zima +update-package package version="": + if [ -n "{{version}}" ]; then scripts/update-local-package {{package}} --version {{version}}; else scripts/update-local-package {{package}}; fi + # Update flake lock file update: nix flake update diff --git a/pkgs/opencode/package.nix b/pkgs/opencode/package.nix new file mode 100644 index 0000000..c83102f --- /dev/null +++ b/pkgs/opencode/package.nix @@ -0,0 +1,179 @@ +{ + lib, + stdenvNoCC, + bun, + fetchFromGitHub, + makeBinaryWrapper, + models-dev, + ripgrep, + sysctl, + installShellFiles, + versionCheckHook, + writableTmpDirAsHomeHook, +}: +let + pname = "opencode"; + version = "1.2.24"; + + src = fetchFromGitHub { + owner = "anomalyco"; + repo = "opencode"; + tag = "v${version}"; + hash = "sha256-smGIc6lYWSjfmGAikoYpP7GbB6mWacrPWrRtp/+HJ3E="; + }; + nodeModulesHashes = { + x86_64-linux = "sha256-4kjoJ06VNvHltPHfzQRBG0bC6R39jao10ffGzrNZ230="; + aarch64-linux = "sha256-6Uio+S2rcyBWbBEeOZb9N1CCKgkbKi68lOIKi3Ws/pQ="; + aarch64-darwin = "sha256-8ngN5KVN4vhdsk0QJ11BGgSVBrcaEbwSj23c77HBpgs="; + x86_64-darwin = "sha256-v/ueYGb9a0Nymzy+mkO4uQr78DAuJnES1qOT0onFgnQ="; + }; + + platform = stdenvNoCC.hostPlatform; + bunCpu = if platform.isAarch64 then "arm64" else "x64"; + bunOs = if platform.isLinux then "linux" else "darwin"; + + node_modules = stdenvNoCC.mkDerivation { + pname = "${pname}-node_modules"; + inherit version src; + + impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ + "GIT_PROXY_COMMAND" + "SOCKS_SERVER" + ]; + + nativeBuildInputs = [ + bun + writableTmpDirAsHomeHook + ]; + + dontConfigure = true; + + buildPhase = '' + runHook preBuild + + export BUN_INSTALL_CACHE_DIR=$(mktemp -d) + + bun install \ + --cpu="${bunCpu}" \ + --os="${bunOs}" \ + --filter '!./' \ + --filter './packages/opencode' \ + --filter './packages/desktop' \ + --frozen-lockfile \ + --ignore-scripts \ + --no-progress + + bun --bun ${src}/nix/scripts/canonicalize-node-modules.ts + bun --bun ${src}/nix/scripts/normalize-bun-binaries.ts + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out + find . -type d -name node_modules -exec cp -R --parents {} $out \; + + runHook postInstall + ''; + + dontFixup = true; + outputHashAlgo = "sha256"; + outputHashMode = "recursive"; + outputHash = nodeModulesHashes.${platform.system}; + }; +in +stdenvNoCC.mkDerivation (finalAttrs: { + inherit + pname + version + src + node_modules + ; + + nativeBuildInputs = [ + bun + installShellFiles + makeBinaryWrapper + models-dev + writableTmpDirAsHomeHook + ]; + + postPatch = '' + substituteInPlace packages/script/src/index.ts \ + --replace-fail 'throw new Error(`This script requires bun@''${expectedBunVersionRange}' \ + 'console.warn(`Warning: This script requires bun@''${expectedBunVersionRange}' + ''; + + configurePhase = '' + runHook preConfigure + + cp -R ${finalAttrs.node_modules}/. . + + runHook postConfigure + ''; + + env.MODELS_DEV_API_JSON = "${models-dev}/dist/_api.json"; + env.OPENCODE_DISABLE_MODELS_FETCH = true; + env.OPENCODE_VERSION = finalAttrs.version; + env.OPENCODE_CHANNEL = "stable"; + + buildPhase = '' + runHook preBuild + + cd ./packages/opencode + bun --bun ./script/build.ts --single --skip-install + bun --bun ./script/schema.ts schema.json + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + install -Dm755 dist/opencode-*/bin/opencode $out/bin/opencode + install -Dm644 schema.json $out/share/opencode/schema.json + + wrapProgram $out/bin/opencode \ + --prefix PATH : ${ + lib.makeBinPath ( + [ + ripgrep + ] + ++ lib.optional platform.isDarwin sysctl + ) + } + + runHook postInstall + ''; + + postInstall = lib.optionalString (stdenvNoCC.buildPlatform.canExecute platform) '' + installShellCompletion --cmd opencode \ + --bash <($out/bin/opencode completion) \ + --zsh <(SHELL=/bin/zsh $out/bin/opencode completion) + ''; + + nativeInstallCheckInputs = [ + versionCheckHook + writableTmpDirAsHomeHook + ]; + doInstallCheck = true; + versionCheckKeepEnvironment = [ + "HOME" + "OPENCODE_DISABLE_MODELS_FETCH" + ]; + versionCheckProgramArg = "--version"; + + passthru = { + jsonschema = "${placeholder "out"}/share/opencode/schema.json"; + }; + + meta = { + description = "The open source coding agent"; + homepage = "https://opencode.ai/"; + license = lib.licenses.mit; + mainProgram = "opencode"; + platforms = builtins.attrNames nodeModulesHashes; + }; +})