nixcfg/modules/nixos/services/opencode/default.nix
Harald Hoyer 3a1cb7487a refactor(opencode): extract serve service into shared NixOS module
New `metacfg.services.opencode` module under modules/nixos/services/opencode/
with options for port, user, homeDir, sopsFile, and extraPackages. User and
homeDir default off `metacfg.user`. Host configs for amd and sgx reduce to
enabling the module and pointing at their respective sops file.

Service PATH gains jq, yq-go, python3, gh, gnutar, gzip, unzip, wget,
diffutils, patch, file, tree, bun, uv, ast-grep, claude-code, and tmux for
agent ergonomics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 13:43:27 +02:00

115 lines
2.8 KiB
Nix

{
config,
pkgs,
lib,
...
}:
with lib;
with lib.metacfg;
let
cfg = config.metacfg.services.opencode;
in
{
options.metacfg.services.opencode = with types; {
enable = mkBoolOpt false "Whether or not to enable the OpenCode web server.";
port = mkOption {
type = types.port;
default = 4196;
description = "Port for the OpenCode web server to listen on.";
};
user = mkOption {
type = types.str;
default = config.metacfg.user.name;
defaultText = literalExpression "config.metacfg.user.name";
description = "User to run the OpenCode service as.";
};
homeDir = mkOption {
type = types.path;
default = config.users.users.${cfg.user}.home;
defaultText = literalExpression "config.users.users.\${cfg.user}.home";
description = "Home directory used as the working directory for the service.";
};
sopsFile = mkOption {
type = types.path;
description = "Path to the sops-encrypted yaml file containing opencode-web-password.";
};
extraPackages = mkOption {
type = types.listOf types.package;
default = [ ];
description = "Additional packages to add to the service PATH.";
};
};
config = mkIf cfg.enable {
systemd.services.opencode-serve = {
description = "OpenCode Web Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path =
(with pkgs; [
git
bash
coreutils
findutils
gnused
gnugrep
gawk
gnumake
nix
nodejs
ripgrep
fd
curl
which
jq
yq-go
python3
gh
gnutar
gzip
unzip
wget
diffutils
patch
file
tree
bun
uv
ast-grep
claude-code
tmux
])
++ cfg.extraPackages;
environment = {
HOME = cfg.homeDir;
LD_LIBRARY_PATH = "${pkgs.stdenv.cc.cc.lib}/lib";
};
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = "users";
WorkingDirectory = cfg.homeDir;
ExecStart = "${pkgs.opencode}/bin/opencode serve --hostname 127.0.0.1 --port ${toString cfg.port}";
Restart = "always";
RestartSec = 5;
EnvironmentFile = config.sops.secrets.opencode-web-password.path;
# Security hardening
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = false;
NoNewPrivileges = true;
ReadWritePaths = [ cfg.homeDir ];
};
};
sops.secrets.opencode-web-password = {
inherit (cfg) sopsFile;
owner = cfg.user;
restartUnits = [ "opencode-serve.service" ];
};
};
}