{ 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" ]; }; }; }