Skip to main content
Glama

server_lock

Harden servers to production standards by applying 19 security steps including SSH key-only authentication, firewall configuration, system hardening, and integrity monitoring. Requires explicit confirmation for production deployment.

Instructions

Harden a server to production standard. Applies 19 hardening steps in a single SSH session: SSH key-only auth, fail2ban, UFW firewall, SSH cipher blacklist, sysctl hardening, unattended-upgrades, login banners, account locking, cloud metadata block, DNS security, APT validation, resource limits, service disabling, backup permissions, password quality policy, Docker daemon hardening (no-new-privileges, log rotation, live-restore, icc), auditd, log retention, and AIDE integrity. Requires production=true to confirm intent (safety gate). Pass dryRun=true to preview changes without applying. Platform-aware: preserves Coolify port 8000 or Dokploy port 3000 in UFW rules. Shows audit score before and after hardening. Requires SSH access to target server. For fine-grained SSH hardening, firewall port rules, or domain management, use server_secure instead.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
serverNoServer name or IP. Auto-selected if only one server exists.
productionNoSet to true to confirm hardening intent. Required to apply 19 hardening steps (safety gate). Omit or pass false to preview with dryRun=true.
dryRunNoPreview changes without applying. Returns what would be done. Bypasses the production safety gate.
forceNoForce lock even if server already appears hardened.

Implementation Reference

  • The handleServerLock function, which executes the server hardening process by applying 19 security steps via applyLock.
    export async function handleServerLock(params: {
      server?: string;
      production?: boolean;
      dryRun?: boolean;
      force?: boolean;
    }, mcpServer?: McpServer): Promise<McpResponse> {
      try {
        const servers = getServers();
        if (servers.length === 0) {
          return mcpError("No servers found", undefined, [
            { command: "kastell add", reason: "Add a server first" },
          ]);
        }
    
        const server = resolveServerForMcp(params, servers);
        if (!server) {
          if (params.server) {
            return mcpError(
              `Server not found: ${params.server}`,
              `Available servers: ${servers.map((s) => s.name).join(", ")}`,
            );
          }
          return mcpError(
            "Multiple servers found. Specify which server to use.",
            `Available: ${servers.map((s) => s.name).join(", ")}`,
          );
        }
    
        const production = params.production ?? false;
        const dryRun = params.dryRun ?? false;
        const force = params.force ?? false;
    
        // Safety gate: require explicit production=true unless doing a dry run
        if (!production && !dryRun) {
          return mcpError(
            "Pass production=true to confirm hardening intent. This applies 19 hardening steps in 4 groups: SSH & Auth (SSH config, fail2ban, login banners, account locking, SSH cipher blacklist), Firewall & Network (UFW, cloud metadata block, DNS security), System (sysctl, unattended-upgrades, APT validation, resource limits, service disabling, backup permissions, password quality, Docker hardening), Monitoring (auditd, log retention, AIDE integrity).",
            "Use dryRun=true to preview changes without applying.",
          );
        }
    
        // Resolve platform from server record (same pattern as serverAudit.ts line 44)
        const platformStr = server.platform ?? server.mode;
        const platform: Platform | undefined =
          platformStr === "coolify" || platformStr === "dokploy" ? platformStr : undefined;
    
        await mcpLog(mcpServer, `Starting 19-step hardening on ${server.name}`);
    
        const result = await applyLock(server.ip, server.name, platform, {
          production,
          dryRun,
          force,
        });
    
        if (!result.success) {
          return mcpError(result.error ?? "Lock hardening failed", result.hint);
        }
    
        await mcpLog(mcpServer, "Hardening complete");
    
        return mcpSuccess({
          success: result.success,
          steps: result.steps,
          ...(result.stepErrors && { stepErrors: result.stepErrors }),
          scoreBefore: result.scoreBefore,
          scoreAfter: result.scoreAfter,
        });
      } catch (error: unknown) {
        return mcpError(getErrorMessage(error));
      }
    }
  • The schema definition for the server_lock tool inputs, including production, dryRun, and force flags.
    export const serverLockSchema = {
      server: z.string().optional().describe("Server name or IP. Auto-selected if only one server exists."),
      production: z.boolean().default(false).describe("Set to true to confirm hardening intent. Required to apply 19 hardening steps (safety gate). Omit or pass false to preview with dryRun=true."),
      dryRun: z.boolean().default(false).describe("Preview changes without applying. Returns what would be done. Bypasses the production safety gate."),
      force: z.boolean().default(false).describe("Force lock even if server already appears hardened."),
    };
  • Registration of the server_lock tool within the MCP server setup.
    server.registerTool("server_lock", {
      description:
        "Harden a server to production standard. Applies 19 hardening steps in a single SSH session: SSH key-only auth, fail2ban, UFW firewall, SSH cipher blacklist, sysctl hardening, unattended-upgrades, login banners, account locking, cloud metadata block, DNS security, APT validation, resource limits, service disabling, backup permissions, password quality policy, Docker daemon hardening (no-new-privileges, log rotation, live-restore, icc), auditd, log retention, and AIDE integrity. Requires production=true to confirm intent (safety gate). Pass dryRun=true to preview changes without applying. Platform-aware: preserves Coolify port 8000 or Dokploy port 3000 in UFW rules. Shows audit score before and after hardening. Requires SSH access to target server. For fine-grained SSH hardening, firewall port rules, or domain management, use server_secure instead.",
      inputSchema: serverLockSchema,
      annotations: {
        title: "Server Lock",
        readOnlyHint: false,
        destructiveHint: false,
        idempotentHint: true,
        openWorldHint: true,
      },
    }, async (params) => {
      return handleServerLock(params, server);
    });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kastelldev/kastell'

If you have feedback or need assistance with the MCP directory API, please join our Discord server