@ebowwa/hetzner 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Kernel Hardening Cloud-Init Components
3
+ *
4
+ * Composable cloud-init blocks for securing the Linux kernel on new servers.
5
+ * Implements 2026 best practices for network stack hardening, IP spoofing
6
+ * protection, SYN flood mitigation, and secure core dump policies.
7
+ *
8
+ * Background: Public-facing VPS servers are constantly probed and attacked.
9
+ * Default Linux kernel settings prioritize compatibility over security. This
10
+ * module applies CIS Benchmark-aligned hardening via /etc/sysctl.d/ which
11
+ * persists across reboots and overrides defaults.
12
+ *
13
+ * Three composable functions return cloud-init line arrays for splicing into
14
+ * the appropriate YAML sections:
15
+ * - kernelHardeningPackages() → packages: section (currently empty, reserved)
16
+ * - kernelHardeningWriteFiles() → write_files: section (drops sysctl config)
17
+ * - kernelHardeningRunCmd() → runcmd: section (applies settings immediately)
18
+ *
19
+ * Security Measures Implemented:
20
+ * 1. Network Stack Hardening: SYN cookies, ICMP rate limits, martian packet logging
21
+ * 2. IP Spoofing Protection: Reverse path filtering, source address verification
22
+ * 3. SYN Flood Protection: TCP SYN cookies, reuse time_wait connections
23
+ * 4. Core Dump Restrictions: Disable setuid dumps, limit core dump size to 0
24
+ * 5. File Permissions: Hard links, symlinks, FIFO protection
25
+ * 6. Memory Protection: ASLR, randomize_va_space
26
+ *
27
+ * References:
28
+ * - CIS Benchmark for Ubuntu Linux 24.04
29
+ * - NIST SP 800-53 Revision 5
30
+ * - https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
31
+ */
32
+ /**
33
+ * Packages required for kernel hardening.
34
+ * Returns cloud-init YAML lines for the `packages:` section.
35
+ *
36
+ * Note: All kernel hardening is done via sysctl configuration, which uses
37
+ * built-in kernel functionality. No additional packages are required.
38
+ * This function is reserved for future expansion (e.g., auditd, kexec-tools).
39
+ */
40
+ export declare function kernelHardeningPackages(): string[];
41
+ /**
42
+ * Kernel sysctl configuration file for comprehensive hardening.
43
+ * Returns cloud-init YAML lines for the `write_files:` section.
44
+ *
45
+ * Drops /etc/sysctl.d/99-security-hardening.conf which:
46
+ * - Takes precedence over /etc/sysctl.conf (99- prefix ensures last load)
47
+ * - Persists across reboots (sysctl.d files are applied on boot)
48
+ * - Can be applied immediately via `sysctl --system` (see runcmd)
49
+ *
50
+ * Settings organized by category:
51
+ * 1. IP Spoofing Protection: rp_filter, secure redirects
52
+ * 2. SYN Flood Protection: syncookies, tcp_tw_reuse
53
+ * 3. Network Stack: ICMP rate limits, martian logging, ignore broadcasts
54
+ * 4. Core Dumps: Disabled for setuid programs, limited for all processes
55
+ * 5. Memory Protection: ASLR, randomize_va_space
56
+ * 6. Filesystem: Hard link/symlink protection
57
+ */
58
+ export declare function kernelHardeningWriteFiles(): string[];
59
+ /**
60
+ * Commands to apply kernel hardening settings immediately at first boot.
61
+ * Returns cloud-init YAML lines for the `runcmd:` section.
62
+ *
63
+ * Order matters:
64
+ * 1. Load all sysctl settings from /etc/sysctl.d/*.conf
65
+ * 2. Apply settings immediately (don't wait for reboot)
66
+ * 3. Log applied settings for audit trail
67
+ * 4. Display summary for cloud-init output verification
68
+ */
69
+ export declare function kernelHardeningRunCmd(): string[];
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Security Audit Cloud-Init Components
3
+ *
4
+ * Composable cloud-init blocks for running post-bootstrap security audits.
5
+ * Generates comprehensive security reports for verification and compliance.
6
+ *
7
+ * This module runs LAST in the bootstrap sequence, after all other security
8
+ * hardening is applied. It captures the state of the system for verification.
9
+ *
10
+ * Three composable functions return cloud-init line arrays for splicing into
11
+ * the appropriate YAML sections:
12
+ * - securityAuditPackages() → packages: section
13
+ * - securityAuditWriteFiles() → write_files: section
14
+ * - securityAuditRunCmd() → runcmd: section
15
+ */
16
+ /**
17
+ * Packages required for security auditing.
18
+ * Returns cloud-init YAML lines for the `packages:` section.
19
+ *
20
+ * - lynis: Comprehensive security auditing tool
21
+ */
22
+ export declare function securityAuditPackages(): string[];
23
+ /**
24
+ * Files to write at first boot for security auditing.
25
+ * Returns cloud-init YAML lines for the `write_files:` section.
26
+ *
27
+ * Drops 1 file onto the server:
28
+ *
29
+ * 1. /opt/monitoring/security-audit.sh
30
+ * - Collects security metrics (UFW, fail2ban, sshd, sysctl)
31
+ * - Runs Lynis audit with warnings-only output
32
+ * - Generates JSON report at /var/log/security-audit.json
33
+ * - Logs summary to /var/log/security-audit.log
34
+ */
35
+ export declare function securityAuditWriteFiles(): string[];
36
+ /**
37
+ * Commands to run security audit at first boot.
38
+ * Returns cloud-init YAML lines for the `runcmd:` section.
39
+ *
40
+ * Order matters:
41
+ * 1. Create /opt/monitoring directory (audit script target)
42
+ * 2. Run security audit script (captures state after all hardening)
43
+ * 3. Log audit completion for verification
44
+ */
45
+ export declare function securityAuditRunCmd(): string[];
@@ -0,0 +1,67 @@
1
+ /**
2
+ * SSH Hardening Cloud-Init Components
3
+ *
4
+ * Composable cloud-init blocks for securing sshd on new servers.
5
+ * Includes: hardened sshd config, fail2ban, and health monitoring.
6
+ *
7
+ * Background: Hetzner public IPs get brute-forced constantly (~5k failed SSH
8
+ * logins per 24h observed on genesis). Without hardening, the default sshd
9
+ * MaxStartups (10:30:100) gets overwhelmed and legitimate connections time out
10
+ * with "Timed out while waiting for handshake".
11
+ *
12
+ * This module is imported by both cloud-init.ts (seed/worker nodes) and
13
+ * genesis.ts (control plane) so every new server gets hardened at first boot.
14
+ *
15
+ * Three composable functions return cloud-init line arrays for splicing into
16
+ * the appropriate YAML sections:
17
+ * - sshdHardeningPackages() → packages: section
18
+ * - sshdHardeningWriteFiles() → write_files: section
19
+ * - sshdHardeningRunCmd() → runcmd: section
20
+ */
21
+ /**
22
+ * Packages required for SSH hardening.
23
+ * Returns cloud-init YAML lines for the `packages:` section.
24
+ *
25
+ * - fail2ban: bans IPs after repeated failed SSH attempts (3 tries → 1hr ban)
26
+ */
27
+ export declare function sshdHardeningPackages(): string[];
28
+ /**
29
+ * Files to write at first boot for SSH hardening.
30
+ * Returns cloud-init YAML lines for the `write_files:` section.
31
+ *
32
+ * Drops 5 files onto the server:
33
+ *
34
+ * 1. /etc/ssh/sshd_config.d/hardened.conf
35
+ * - Disables password auth entirely (key-only)
36
+ * - Raises MaxStartups from default 10:30:100 → 20:50:60 so brute-force
37
+ * traffic doesn't starve legitimate connections
38
+ * - Reduces LoginGraceTime from 2min → 30s (attackers hold slots open)
39
+ * - Limits MaxAuthTries to 3 per connection
40
+ * - Enables keepalive (30s interval, 3 missed = disconnect)
41
+ *
42
+ * 2. /etc/fail2ban/jail.local
43
+ * - Monitors sshd via systemd journal
44
+ * - Bans IP for 1 hour after 3 failures within 10 minutes
45
+ * - Uses nftables (Ubuntu 24.04 default firewall backend)
46
+ *
47
+ * 3. /opt/monitoring/sshd-health.sh
48
+ * - Collects sshd + fail2ban + system metrics into JSON
49
+ * - Writes to /var/log/sshd-health.json (read by the app via SSH)
50
+ * - Auto-restarts sshd if it detects it's down
51
+ *
52
+ * 4. /etc/systemd/system/sshd-health.service (oneshot runner)
53
+ * 5. /etc/systemd/system/sshd-health.timer (runs every 60 seconds)
54
+ */
55
+ export declare function sshdHardeningWriteFiles(): string[];
56
+ /**
57
+ * Commands to activate all SSH hardening services at first boot.
58
+ * Returns cloud-init YAML lines for the `runcmd:` section.
59
+ *
60
+ * Order matters:
61
+ * 1. Create /opt/monitoring dir (health script target)
62
+ * 2. Reload sshd to pick up hardened.conf (fallback: full restart)
63
+ * 3. Enable + start fail2ban (reads jail.local immediately)
64
+ * 4. Reload systemd to pick up the health service/timer units
65
+ * 5. Enable + start the health timer (begins 60s monitoring loop)
66
+ */
67
+ export declare function sshdHardeningRunCmd(): string[];
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Hetzner Cloud API client
3
+ * For server-side use only (requires API token)
4
+ *
5
+ * TODO: RE-REVIEW https://docs.hetzner.cloud/reference/cloud#authentication
6
+ * - https://tailscale.com/kb/1150/cloud-hetzner
7
+ */
8
+ import { ServerOperations } from "./servers.js";
9
+ import { ActionOperations } from "./actions.js";
10
+ import { PricingOperations } from "./pricing.js";
11
+ import { SSHKeyOperations } from "./ssh-keys.js";
12
+ import { VolumeOperations } from "./volumes.js";
13
+ import type { RateLimitInfo } from "./types.js";
14
+ export declare class HetznerClient {
15
+ private apiToken;
16
+ constructor(apiToken?: string);
17
+ get isAuthenticated(): boolean;
18
+ /**
19
+ * Make a request to the Hetzner Cloud API
20
+ *
21
+ * @param endpoint - API endpoint (e.g., "/servers")
22
+ * @param options - RequestInit options
23
+ * @returns Parsed JSON response
24
+ * @throws {HetznerAPIError} On API errors
25
+ */
26
+ request<T>(endpoint: string, options?: RequestInit): Promise<T>;
27
+ /**
28
+ * Validate Hetzner API response with Zod schema
29
+ *
30
+ * @param schema - Zod schema to validate against
31
+ * @param data - Data to validate
32
+ * @returns Validated data
33
+ */
34
+ private validateResponse;
35
+ /**
36
+ * Handle rate limit information from response headers
37
+ *
38
+ * @param rateLimit - Rate limit info from response
39
+ */
40
+ private handleRateLimit;
41
+ /**
42
+ * Get current rate limit information
43
+ *
44
+ * Makes a lightweight request to check rate limit status
45
+ *
46
+ * @returns Rate limit info or null if not available
47
+ */
48
+ getRateLimit(): Promise<RateLimitInfo | null>;
49
+ readonly servers: ServerOperations;
50
+ readonly actions: ActionOperations;
51
+ readonly pricing: PricingOperations;
52
+ readonly ssh_keys: SSHKeyOperations;
53
+ readonly volumes: VolumeOperations;
54
+ listServers(): Promise<import("./types.js").HetznerServer[]>;
55
+ getServer(id: number): Promise<import("./types.js").HetznerServer>;
56
+ createServer(options: import("./types.js").CreateServerOptions): Promise<import("./types.js").CreateServerResponse>;
57
+ deleteServer(id: number): Promise<import("./types.js").HetznerAction>;
58
+ powerOn(id: number): Promise<import("./types.js").HetznerAction>;
59
+ powerOff(id: number): Promise<import("./types.js").HetznerAction>;
60
+ reboot(id: number): Promise<import("./types.js").HetznerAction>;
61
+ }
62
+ export type * from "./types.js";
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Hetzner Cloud API configuration
3
+ */
4
+ export declare const HETZNER_API_BASE = "https://api.hetzner.cloud/v1";
Binary file
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Hetzner Cloud API error types and utilities
3
+ */
4
+ import type { RateLimitInfo, ActionError } from "./types.js";
5
+ export type { ActionError };
6
+ /**
7
+ * Hetzner API error codes
8
+ * @see https://docs.hetzner.cloud/#errors
9
+ */
10
+ export declare enum HetznerErrorCode {
11
+ Unauthorized = "unauthorized",
12
+ InvalidInput = "invalid_input",
13
+ JSONError = "json_error",
14
+ Forbidden = "forbidden",
15
+ NotFound = "not_found",
16
+ ResourceLocked = "locked",
17
+ ResourceLimitExceeded = "resource_limit_exceeded",
18
+ UniquenessError = "uniqueness_error",
19
+ RateLimitExceeded = "rate_limit_exceeded",
20
+ Conflict = "conflict",
21
+ ServiceError = "service_error",
22
+ ServerNotStopped = "server_not_stopped",
23
+ ServerAlreadyStopped = "server_already_stopped",
24
+ InvalidServerType = "invalid_server_type",
25
+ IpNotOwned = "ip_not_owned",
26
+ IpAlreadyAssigned = "ip_already_assigned",
27
+ VolumeAlreadyAttached = "volume_already_attached",
28
+ VolumeSizeNotMultiple = "volume_size_not_multiple",
29
+ FirewallInUse = "firewall_in_use",
30
+ CertificateValidationFailed = "certificate_validation_failed",
31
+ CertificatePending = "certificate_pending"
32
+ }
33
+ /**
34
+ * Base Hetzner API error
35
+ */
36
+ export declare class HetznerAPIError extends Error {
37
+ code?: string;
38
+ details?: unknown;
39
+ constructor(message: string, code?: string, details?: unknown);
40
+ }
41
+ /**
42
+ * Authentication error (401)
43
+ */
44
+ export declare class HetznerUnauthorizedError extends HetznerAPIError {
45
+ constructor(message?: string);
46
+ }
47
+ /**
48
+ * Forbidden error (403)
49
+ */
50
+ export declare class HetznerForbiddenError extends HetznerAPIError {
51
+ constructor(message?: string);
52
+ }
53
+ /**
54
+ * Resource not found error (404)
55
+ */
56
+ export declare class HetznerNotFoundError extends HetznerAPIError {
57
+ constructor(resource: string, id: number | string);
58
+ }
59
+ /**
60
+ * Rate limit exceeded error (429)
61
+ */
62
+ export declare class HetznerRateLimitError extends HetznerAPIError {
63
+ rateLimitInfo?: RateLimitInfo;
64
+ constructor(message?: string, rateLimitInfo?: RateLimitInfo);
65
+ /**
66
+ * Get the number of milliseconds until the rate limit resets
67
+ */
68
+ get resetInMs(): number;
69
+ /**
70
+ * Get a human-readable reset time
71
+ */
72
+ get resetTime(): string;
73
+ }
74
+ /**
75
+ * Resource locked error
76
+ */
77
+ export declare class HetznerResourceLockedError extends HetznerAPIError {
78
+ actionInProgress?: string;
79
+ constructor(resource: string, id: number | string, actionInProgress?: string);
80
+ }
81
+ /**
82
+ * Resource limit exceeded error
83
+ */
84
+ export declare class HetznerResourceLimitError extends HetznerAPIError {
85
+ constructor(resource: string, limit: number);
86
+ }
87
+ /**
88
+ * Invalid input error
89
+ */
90
+ export declare class HetznerInvalidInputError extends HetznerAPIError {
91
+ fields?: Record<string, string>;
92
+ constructor(message: string, fields?: Record<string, string>);
93
+ }
94
+ /**
95
+ * Conflict error
96
+ */
97
+ export declare class HetznerConflictError extends HetznerAPIError {
98
+ constructor(message: string, details?: unknown);
99
+ }
100
+ /**
101
+ * Service error (5xx)
102
+ */
103
+ export declare class HetznerServiceError extends HetznerAPIError {
104
+ statusCode?: number;
105
+ constructor(message: string, statusCode?: number);
106
+ }
107
+ /**
108
+ * Action failed error
109
+ */
110
+ export declare class HetznerActionError extends HetznerAPIError {
111
+ actionError: ActionError;
112
+ actionId: number;
113
+ constructor(actionError: ActionError, actionId: number);
114
+ }
115
+ /**
116
+ * Timeout error for action polling
117
+ */
118
+ export declare class HetznerTimeoutError extends HetznerAPIError {
119
+ lastProgress: number;
120
+ constructor(actionId: number, timeout: number, lastProgress: number);
121
+ }
122
+ /**
123
+ * Parse Hetzner API error response and create appropriate error
124
+ */
125
+ export declare function createHetznerError(statusCode: number, body: {
126
+ error?: {
127
+ code: string;
128
+ message: string;
129
+ details?: unknown;
130
+ };
131
+ }): HetznerAPIError;
132
+ /**
133
+ * Check if an error is retryable
134
+ */
135
+ export declare function isRetryableError(error: unknown): boolean;
136
+ /**
137
+ * Check if an error is a rate limit error
138
+ */
139
+ export declare function isRateLimitError(error: unknown): error is HetznerRateLimitError;
140
+ /**
141
+ * Check if an error is a resource locked error
142
+ */
143
+ export declare function isResourceLockedError(error: unknown): error is HetznerResourceLockedError;
144
+ /**
145
+ * Calculate retry delay with exponential backoff
146
+ */
147
+ export declare function calculateRetryDelay(attempt: number, baseDelay?: number, maxDelay?: number): number;
148
+ /**
149
+ * Error handler function type
150
+ */
151
+ export type ErrorHandler = (error: HetznerAPIError) => void | Promise<void>;
152
+ /**
153
+ * Error handler options
154
+ */
155
+ export interface ErrorHandlerContext {
156
+ /** Maximum number of retry attempts */
157
+ maxRetries?: number;
158
+ /** Base delay for exponential backoff in milliseconds */
159
+ baseDelay?: number;
160
+ /** Maximum delay between retries in milliseconds */
161
+ maxDelay?: number;
162
+ /** Optional error handler callback */
163
+ onError?: ErrorHandler;
164
+ /** Whether to log errors */
165
+ logErrors?: boolean;
166
+ }
167
+ /**
168
+ * Default error handler that logs to console
169
+ */
170
+ export declare function defaultErrorHandler(error: HetznerAPIError): void;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Hetzner Cloud API client
3
+ * For server-side use only (requires API token)
4
+ *
5
+ * TODO:
6
+ * - Certificate actions: https://docs.hetzner.cloud/reference/cloud#certificate-actions
7
+ * - DNS operations
8
+ */
9
+ export { HetznerClient } from "./client.js";
10
+ export { ServerOperations } from "./servers.js";
11
+ export { VolumeOperations } from "./volumes.js";
12
+ export { ActionOperations } from "./actions.js";
13
+ export { SSHKeyOperations } from "./ssh-keys.js";
14
+ export { getTokenFromCLI, isAuthenticated, resolveApiToken } from "./auth.js";
15
+ export { HETZNER_API_BASE } from "./config.js";
16
+ export * from "./types.js";
17
+ export * from "./schemas.js";
18
+ export * from "./errors.js";
19
+ export { waitForAction, waitForMultipleActions, waitForMultipleActionsWithLimit, batchCheckActions, getActionTimeout, isActionRunning, isActionSuccess, isActionError, formatActionProgress, getActionDescription, getPollInterval, getAdaptivePollInterval, waitForActionAdaptive, parseRateLimitHeaders, isRateLimitLow, formatRateLimitStatus, waitForRateLimitReset, createProgressLogger, ACTION_TIMEOUTS, } from "./actions.js";
20
+ export * from "./bootstrap/index.js";
21
+ export * from "./onboarding/index.js";
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Claude Code Onboarding
3
+ *
4
+ * Install and configure Claude Code on remote servers.
5
+ * Uses official installer: curl -fsSL https://claude.ai/install.sh | bash
6
+ */
7
+ import type { SSHOptions } from "@ebowwa/terminal/types";
8
+ export interface ClaudeConfig {
9
+ /** Skip installation if already installed */
10
+ skipIfInstalled?: boolean;
11
+ }
12
+ /**
13
+ * Install Claude Code on a remote server
14
+ *
15
+ * @param host - Server IP or hostname
16
+ * @param config - Claude configuration
17
+ * @param sshOptions - SSH options
18
+ * @returns Success status
19
+ */
20
+ export declare function onboardClaude(host: string, config?: ClaudeConfig, sshOptions?: Partial<SSHOptions>): Promise<{
21
+ success: boolean;
22
+ message: string;
23
+ version?: string;
24
+ }>;
25
+ /**
26
+ * Check Claude Code status on a remote server
27
+ *
28
+ * @param host - Server IP or hostname
29
+ * @param sshOptions - SSH options
30
+ * @returns Claude status
31
+ */
32
+ export declare function checkClaudeStatus(host: string, sshOptions?: Partial<SSHOptions>): Promise<{
33
+ configured: boolean;
34
+ version?: string;
35
+ path?: string;
36
+ message: string;
37
+ }>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Doppler Onboarding
3
+ *
4
+ * Configure Doppler CLI service token on remote servers.
5
+ * This enables doppler run to inject secrets into processes.
6
+ */
7
+ import type { SSHOptions } from "@ebowwa/terminal/types";
8
+ export interface DopplerConfig {
9
+ token: string;
10
+ project?: string;
11
+ config?: string;
12
+ }
13
+ /**
14
+ * Configure Doppler on a remote server
15
+ *
16
+ * @param host - Server IP or hostname
17
+ * @param config - Doppler configuration
18
+ * @param sshOptions - SSH options
19
+ * @returns Success status
20
+ */
21
+ export declare function onboardDoppler(host: string, config: DopplerConfig, sshOptions?: Partial<SSHOptions>): Promise<{
22
+ success: boolean;
23
+ message: string;
24
+ }>;
25
+ /**
26
+ * Check Doppler status on a remote server
27
+ *
28
+ * @param host - Server IP or hostname
29
+ * @param sshOptions - SSH options
30
+ * @returns Doppler status
31
+ */
32
+ export declare function checkDopplerStatus(host: string, sshOptions?: Partial<SSHOptions>): Promise<{
33
+ configured: boolean;
34
+ project?: string;
35
+ config?: string;
36
+ message: string;
37
+ }>;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Git Onboarding
3
+ *
4
+ * Configure Git credentials on remote servers.
5
+ * Sets up GitHub token for gh cli and git credential helper.
6
+ */
7
+ import type { SSHOptions } from "@ebowwa/terminal/types";
8
+ export interface GitConfig {
9
+ username?: string;
10
+ email?: string;
11
+ githubToken?: string;
12
+ }
13
+ /**
14
+ * Configure Git on a remote server
15
+ *
16
+ * @param host - Server IP or hostname
17
+ * @param config - Git configuration
18
+ * @param sshOptions - SSH options
19
+ * @returns Success status
20
+ */
21
+ export declare function onboardGit(host: string, config: GitConfig, sshOptions?: Partial<SSHOptions>): Promise<{
22
+ success: boolean;
23
+ message: string;
24
+ }>;
25
+ /**
26
+ * Check Git status on a remote server
27
+ *
28
+ * @param host - Server IP or hostname
29
+ * @param sshOptions - SSH options
30
+ * @returns Git status
31
+ */
32
+ export declare function checkGitStatus(host: string, sshOptions?: Partial<SSHOptions>): Promise<{
33
+ configured: boolean;
34
+ username?: string;
35
+ email?: string;
36
+ hasToken: boolean;
37
+ message: string;
38
+ }>;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Hetzner Onboarding Module
3
+ *
4
+ * Post-boot configuration for newly provisioned servers.
5
+ * Handles services that require secrets/tokens:
6
+ * - Doppler (secrets management)
7
+ * - Tailscale (VPN)
8
+ * - Git (credentials)
9
+ * - Claude Code (AI assistant)
10
+ *
11
+ * This is Phase 2 of the bootstrap process, running after
12
+ * cloud-init completes the initial installation.
13
+ */
14
+ export type { OnboardingConfig, OnboardingStatus, OnboardingResult, BatchOnboardingResult, ServiceStatus } from "./types";
15
+ export { onboardDoppler, checkDopplerStatus } from "./doppler";
16
+ export { onboardTailscale, checkTailscaleStatus } from "./tailscale";
17
+ export { onboardGit, checkGitStatus } from "./git";
18
+ export { onboardClaude, checkClaudeStatus } from "./claude";
19
+ export { onboardServer, checkOnboardingStatus, onboardBatch } from "./onboarding";
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Server Onboarding
3
+ *
4
+ * Main onboarding orchestration.
5
+ * Coordinates Doppler, Tailscale, and Git onboarding.
6
+ */
7
+ import type { SSHOptions } from "@ebowwa/terminal/types";
8
+ import type { OnboardingConfig, OnboardingStatus, OnboardingResult, BatchOnboardingResult } from "./types";
9
+ /**
10
+ * Onboard a single server with all configured services
11
+ *
12
+ * @param config - Onboarding configuration
13
+ * @param sshOptions - Additional SSH options
14
+ * @returns Onboarding result
15
+ */
16
+ export declare function onboardServer(config: OnboardingConfig, sshOptions?: Partial<SSHOptions>): Promise<OnboardingResult>;
17
+ /**
18
+ * Check onboarding status of a server
19
+ *
20
+ * @param host - Server IP or hostname
21
+ * @param sshOptions - SSH options
22
+ * @returns Onboarding status
23
+ */
24
+ export declare function checkOnboardingStatus(host: string, sshOptions?: Partial<SSHOptions>): Promise<OnboardingStatus>;
25
+ /**
26
+ * Onboard multiple servers in parallel
27
+ *
28
+ * @param hosts - List of server IPs/hostnames
29
+ * @param sharedConfig - Shared onboarding config for all servers
30
+ * @param sshOptions - SSH options
31
+ * @returns Batch onboarding result
32
+ */
33
+ export declare function onboardBatch(hosts: string[], sharedConfig: Omit<OnboardingConfig, "host">, sshOptions?: Partial<SSHOptions>): Promise<BatchOnboardingResult>;
34
+ /**
35
+ * Quick onboarding check for multiple servers
36
+ *
37
+ * @param hosts - List of server IPs/hostnames
38
+ * @param sshOptions - SSH options
39
+ * @returns Map of host to onboarding status
40
+ */
41
+ export declare function checkBatchStatus(hosts: string[], sshOptions?: Partial<SSHOptions>): Promise<Map<string, OnboardingStatus>>;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Tailscale Onboarding
3
+ *
4
+ * Join Tailscale network on remote servers.
5
+ * Enables secure VPN access to servers.
6
+ */
7
+ import type { SSHOptions } from "@ebowwa/terminal/types";
8
+ export interface TailscaleConfig {
9
+ authKey: string;
10
+ hostname?: string;
11
+ tags?: string[];
12
+ }
13
+ /**
14
+ * Join Tailscale network on a remote server
15
+ *
16
+ * @param host - Server IP or hostname
17
+ * @param config - Tailscale configuration
18
+ * @param sshOptions - SSH options
19
+ * @returns Success status with Tailscale IP
20
+ */
21
+ export declare function onboardTailscale(host: string, config: TailscaleConfig, sshOptions?: Partial<SSHOptions>): Promise<{
22
+ success: boolean;
23
+ message: string;
24
+ tailscaleIp?: string;
25
+ }>;
26
+ /**
27
+ * Check Tailscale status on a remote server
28
+ *
29
+ * @param host - Server IP or hostname
30
+ * @param sshOptions - SSH options
31
+ * @returns Tailscale status
32
+ */
33
+ export declare function checkTailscaleStatus(host: string, sshOptions?: Partial<SSHOptions>): Promise<{
34
+ configured: boolean;
35
+ tailscaleIp?: string;
36
+ hostname?: string;
37
+ message: string;
38
+ }>;