@edgible-team/cli 1.0.1
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.
- package/LICENSE +136 -0
- package/README.md +450 -0
- package/dist/client/api-client.js +1057 -0
- package/dist/client/index.js +21 -0
- package/dist/commands/agent.js +1280 -0
- package/dist/commands/ai.js +608 -0
- package/dist/commands/application.js +885 -0
- package/dist/commands/auth.js +570 -0
- package/dist/commands/base/BaseCommand.js +93 -0
- package/dist/commands/base/CommandHandler.js +7 -0
- package/dist/commands/base/command-wrapper.js +58 -0
- package/dist/commands/base/middleware.js +77 -0
- package/dist/commands/config.js +116 -0
- package/dist/commands/connectivity.js +59 -0
- package/dist/commands/debug.js +98 -0
- package/dist/commands/discover.js +144 -0
- package/dist/commands/examples/migrated-command-example.js +180 -0
- package/dist/commands/gateway.js +494 -0
- package/dist/commands/managedGateway.js +787 -0
- package/dist/commands/utils/config-validator.js +76 -0
- package/dist/commands/utils/gateway-prompt.js +79 -0
- package/dist/commands/utils/input-parser.js +120 -0
- package/dist/commands/utils/output-formatter.js +109 -0
- package/dist/config/app-config.js +99 -0
- package/dist/detection/SystemCapabilityDetector.js +1244 -0
- package/dist/detection/ToolDetector.js +305 -0
- package/dist/detection/WorkloadDetector.js +314 -0
- package/dist/di/bindings.js +99 -0
- package/dist/di/container.js +88 -0
- package/dist/di/types.js +32 -0
- package/dist/index.js +52 -0
- package/dist/interfaces/IDaemonManager.js +3 -0
- package/dist/repositories/config-repository.js +62 -0
- package/dist/repositories/gateway-repository.js +35 -0
- package/dist/scripts/postinstall.js +101 -0
- package/dist/services/AgentStatusManager.js +299 -0
- package/dist/services/ConnectivityTester.js +271 -0
- package/dist/services/DependencyInstaller.js +475 -0
- package/dist/services/LocalAgentManager.js +2216 -0
- package/dist/services/application/ApplicationService.js +299 -0
- package/dist/services/auth/AuthService.js +214 -0
- package/dist/services/aws.js +644 -0
- package/dist/services/daemon/DaemonManagerFactory.js +65 -0
- package/dist/services/daemon/DockerDaemonManager.js +395 -0
- package/dist/services/daemon/LaunchdDaemonManager.js +257 -0
- package/dist/services/daemon/PodmanDaemonManager.js +369 -0
- package/dist/services/daemon/SystemdDaemonManager.js +221 -0
- package/dist/services/daemon/WindowsServiceDaemonManager.js +210 -0
- package/dist/services/daemon/index.js +16 -0
- package/dist/services/edgible.js +3060 -0
- package/dist/services/gateway/GatewayService.js +334 -0
- package/dist/state/config.js +146 -0
- package/dist/types/AgentConfig.js +5 -0
- package/dist/types/AgentStatus.js +5 -0
- package/dist/types/ApiClient.js +5 -0
- package/dist/types/ApiRequests.js +5 -0
- package/dist/types/ApiResponses.js +5 -0
- package/dist/types/Application.js +5 -0
- package/dist/types/CaddyJson.js +5 -0
- package/dist/types/UnifiedAgentStatus.js +56 -0
- package/dist/types/WireGuard.js +5 -0
- package/dist/types/Workload.js +5 -0
- package/dist/types/agent.js +5 -0
- package/dist/types/command-options.js +5 -0
- package/dist/types/connectivity.js +5 -0
- package/dist/types/errors.js +250 -0
- package/dist/types/gateway-types.js +5 -0
- package/dist/types/index.js +48 -0
- package/dist/types/models/ApplicationData.js +5 -0
- package/dist/types/models/CertificateData.js +5 -0
- package/dist/types/models/DeviceData.js +5 -0
- package/dist/types/models/DevicePoolData.js +5 -0
- package/dist/types/models/OrganizationData.js +5 -0
- package/dist/types/models/OrganizationInviteData.js +5 -0
- package/dist/types/models/ProviderConfiguration.js +5 -0
- package/dist/types/models/ResourceData.js +5 -0
- package/dist/types/models/ServiceResourceData.js +5 -0
- package/dist/types/models/UserData.js +5 -0
- package/dist/types/route.js +5 -0
- package/dist/types/validation/schemas.js +218 -0
- package/dist/types/validation.js +5 -0
- package/dist/utils/FileIntegrityManager.js +256 -0
- package/dist/utils/PathMigration.js +219 -0
- package/dist/utils/PathResolver.js +235 -0
- package/dist/utils/PlatformDetector.js +277 -0
- package/dist/utils/console-logger.js +130 -0
- package/dist/utils/docker-compose-parser.js +179 -0
- package/dist/utils/errors.js +130 -0
- package/dist/utils/health-checker.js +155 -0
- package/dist/utils/json-logger.js +72 -0
- package/dist/utils/log-formatter.js +293 -0
- package/dist/utils/logger.js +59 -0
- package/dist/utils/network-utils.js +217 -0
- package/dist/utils/output.js +182 -0
- package/dist/utils/passwordValidation.js +91 -0
- package/dist/utils/progress.js +167 -0
- package/dist/utils/sudo-checker.js +22 -0
- package/dist/utils/urls.js +32 -0
- package/dist/utils/validation.js +31 -0
- package/dist/validation/schemas.js +175 -0
- package/dist/validation/validator.js +67 -0
- package/package.json +83 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DaemonManagerFactory = void 0;
|
|
4
|
+
const SystemdDaemonManager_1 = require("./SystemdDaemonManager");
|
|
5
|
+
const LaunchdDaemonManager_1 = require("./LaunchdDaemonManager");
|
|
6
|
+
const WindowsServiceDaemonManager_1 = require("./WindowsServiceDaemonManager");
|
|
7
|
+
const DockerDaemonManager_1 = require("./DockerDaemonManager");
|
|
8
|
+
const PodmanDaemonManager_1 = require("./PodmanDaemonManager");
|
|
9
|
+
const PlatformDetector_1 = require("../../utils/PlatformDetector");
|
|
10
|
+
class DaemonManagerFactory {
|
|
11
|
+
/**
|
|
12
|
+
* Create a daemon manager instance based on the type
|
|
13
|
+
*/
|
|
14
|
+
static create(type) {
|
|
15
|
+
const platform = PlatformDetector_1.PlatformDetector.getPlatform();
|
|
16
|
+
switch (type) {
|
|
17
|
+
case 'systemd':
|
|
18
|
+
if (platform !== 'linux') {
|
|
19
|
+
throw new Error('systemd is only available on Linux');
|
|
20
|
+
}
|
|
21
|
+
return new SystemdDaemonManager_1.SystemdDaemonManager();
|
|
22
|
+
case 'launchd':
|
|
23
|
+
if (platform !== 'darwin') {
|
|
24
|
+
throw new Error('launchd is only available on macOS');
|
|
25
|
+
}
|
|
26
|
+
return new LaunchdDaemonManager_1.LaunchdDaemonManager();
|
|
27
|
+
case 'windows-service':
|
|
28
|
+
if (platform !== 'win32') {
|
|
29
|
+
throw new Error('Windows Service is only available on Windows');
|
|
30
|
+
}
|
|
31
|
+
return new WindowsServiceDaemonManager_1.WindowsServiceDaemonManager();
|
|
32
|
+
case 'docker':
|
|
33
|
+
return new DockerDaemonManager_1.DockerDaemonManager();
|
|
34
|
+
case 'podman':
|
|
35
|
+
return new PodmanDaemonManager_1.PodmanDaemonManager();
|
|
36
|
+
default:
|
|
37
|
+
throw new Error(`Unknown daemon type: ${type}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get daemon manager from stored config type
|
|
42
|
+
*/
|
|
43
|
+
static fromConfig(installationType) {
|
|
44
|
+
if (!installationType) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const validTypes = ['systemd', 'launchd', 'windows-service', 'docker', 'podman'];
|
|
48
|
+
if (!validTypes.includes(installationType)) {
|
|
49
|
+
throw new Error(`Invalid installation type in config: ${installationType}`);
|
|
50
|
+
}
|
|
51
|
+
return this.create(installationType);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get the recommended daemon manager for the current platform
|
|
55
|
+
*/
|
|
56
|
+
static async getRecommended() {
|
|
57
|
+
const recommendedType = await PlatformDetector_1.PlatformDetector.getRecommendedType();
|
|
58
|
+
if (!recommendedType) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return this.create(recommendedType);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.DaemonManagerFactory = DaemonManagerFactory;
|
|
65
|
+
//# sourceMappingURL=DaemonManagerFactory.js.map
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DockerDaemonManager = void 0;
|
|
37
|
+
const child_process_1 = require("child_process");
|
|
38
|
+
const util_1 = require("util");
|
|
39
|
+
const fs = __importStar(require("fs/promises"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const PlatformDetector_1 = require("../../utils/PlatformDetector");
|
|
42
|
+
const PathResolver_1 = require("../../utils/PathResolver");
|
|
43
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
44
|
+
class DockerDaemonManager {
|
|
45
|
+
constructor() {
|
|
46
|
+
this.containerName = 'edgible-agent';
|
|
47
|
+
this.imageName = 'edgible-agent:latest';
|
|
48
|
+
this.platform = PlatformDetector_1.PlatformDetector.getPlatform();
|
|
49
|
+
}
|
|
50
|
+
async install(config) {
|
|
51
|
+
// Check if image exists locally
|
|
52
|
+
const imageExists = await this.checkImageExists();
|
|
53
|
+
if (!imageExists) {
|
|
54
|
+
throw new Error(`Docker image '${this.imageName}' not found. Please build or pull the image first.\n` +
|
|
55
|
+
` To build: cd agent-v2 && docker build -t ${this.imageName} .\n` +
|
|
56
|
+
` Or pull from registry if available.`);
|
|
57
|
+
}
|
|
58
|
+
// Create Docker container with proper mounts and capabilities
|
|
59
|
+
const dockerRunCommand = this.generateDockerRunCommand(config);
|
|
60
|
+
try {
|
|
61
|
+
// Remove existing container if it exists
|
|
62
|
+
try {
|
|
63
|
+
await execAsync(`docker rm -f ${this.containerName}`);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Container doesn't exist, that's fine
|
|
67
|
+
}
|
|
68
|
+
// Create container
|
|
69
|
+
await execAsync(dockerRunCommand);
|
|
70
|
+
console.log('Docker container created successfully');
|
|
71
|
+
// Create systemd/launchd service wrapper for auto-start on boot
|
|
72
|
+
await this.createServiceWrapper(config);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
throw new Error(`Failed to create Docker container: ${error instanceof Error ? error.message : String(error)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async start() {
|
|
79
|
+
try {
|
|
80
|
+
await execAsync(`docker start ${this.containerName}`);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
throw new Error(`Failed to start container: ${error instanceof Error ? error.message : String(error)}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async stop() {
|
|
87
|
+
try {
|
|
88
|
+
await execAsync(`docker stop ${this.containerName}`);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
throw new Error(`Failed to stop container: ${error instanceof Error ? error.message : String(error)}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async restart() {
|
|
95
|
+
try {
|
|
96
|
+
await execAsync(`docker restart ${this.containerName}`);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
throw new Error(`Failed to restart container: ${error instanceof Error ? error.message : String(error)}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async status() {
|
|
103
|
+
try {
|
|
104
|
+
const { stdout } = await execAsync(`docker ps -a --filter name=${this.containerName} --format "{{.Status}}|||{{.ID}}"`);
|
|
105
|
+
if (!stdout.trim()) {
|
|
106
|
+
return {
|
|
107
|
+
running: false,
|
|
108
|
+
enabled: false,
|
|
109
|
+
message: 'Container not found'
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const [status, containerId] = stdout.trim().split('|||');
|
|
113
|
+
const isRunning = status.toLowerCase().includes('up');
|
|
114
|
+
// Get more detailed info if running
|
|
115
|
+
if (isRunning) {
|
|
116
|
+
const { stdout: inspectOut } = await execAsync(`docker inspect ${containerId} --format "{{.State.Pid}}"`);
|
|
117
|
+
const pid = parseInt(inspectOut.trim(), 10);
|
|
118
|
+
return {
|
|
119
|
+
running: true,
|
|
120
|
+
enabled: true,
|
|
121
|
+
pid: pid || undefined,
|
|
122
|
+
message: status
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
running: false,
|
|
127
|
+
enabled: true,
|
|
128
|
+
message: status
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
return {
|
|
133
|
+
running: false,
|
|
134
|
+
enabled: false,
|
|
135
|
+
message: error instanceof Error ? error.message : String(error)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async logs(follow, lines = 100) {
|
|
140
|
+
const followFlag = follow ? '-f' : '';
|
|
141
|
+
if (follow) {
|
|
142
|
+
const { spawn } = require('child_process');
|
|
143
|
+
const proc = spawn('docker', ['logs', this.containerName, '--tail', String(lines), '-f'], {
|
|
144
|
+
stdio: 'inherit'
|
|
145
|
+
});
|
|
146
|
+
process.on('SIGINT', () => {
|
|
147
|
+
proc.kill('SIGTERM');
|
|
148
|
+
process.exit(0);
|
|
149
|
+
});
|
|
150
|
+
// Return empty string for follow mode as logs are streamed to stdout
|
|
151
|
+
return '';
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
try {
|
|
155
|
+
const { stdout } = await execAsync(`docker logs ${this.containerName} --tail ${lines}`);
|
|
156
|
+
return stdout;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
throw new Error(`Failed to read logs: ${error instanceof Error ? error.message : String(error)}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async enable() {
|
|
164
|
+
// Container is created with --restart unless-stopped, so it's automatically enabled
|
|
165
|
+
// But we also need to enable the systemd/launchd wrapper service
|
|
166
|
+
if (this.platform === 'linux') {
|
|
167
|
+
try {
|
|
168
|
+
await execAsync('systemctl enable edgible-agent-docker');
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
// Service wrapper might not exist yet
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else if (this.platform === 'darwin') {
|
|
175
|
+
try {
|
|
176
|
+
await execAsync('launchctl load /Library/LaunchDaemons/com.edgible.agent.docker.plist');
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
// Service wrapper might not exist yet
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Windows doesn't need explicit enable as Docker Desktop handles startup
|
|
183
|
+
}
|
|
184
|
+
async disable() {
|
|
185
|
+
if (this.platform === 'linux') {
|
|
186
|
+
try {
|
|
187
|
+
await execAsync('systemctl disable edgible-agent-docker');
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
// Ignore errors
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else if (this.platform === 'darwin') {
|
|
194
|
+
try {
|
|
195
|
+
await execAsync('launchctl unload /Library/LaunchDaemons/com.edgible.agent.docker.plist');
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
// Ignore errors
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async uninstall() {
|
|
203
|
+
// Stop and remove container
|
|
204
|
+
try {
|
|
205
|
+
await this.stop();
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// Ignore if already stopped
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
await execAsync(`docker rm ${this.containerName}`);
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
throw new Error(`Failed to remove container: ${error instanceof Error ? error.message : String(error)}`);
|
|
215
|
+
}
|
|
216
|
+
// Remove service wrapper
|
|
217
|
+
await this.removeServiceWrapper();
|
|
218
|
+
}
|
|
219
|
+
getPlatform() {
|
|
220
|
+
return this.platform;
|
|
221
|
+
}
|
|
222
|
+
getType() {
|
|
223
|
+
return 'docker';
|
|
224
|
+
}
|
|
225
|
+
async checkImageExists() {
|
|
226
|
+
try {
|
|
227
|
+
await execAsync(`docker image inspect ${this.imageName}`);
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async buildImage(agentPath) {
|
|
235
|
+
// Look for Dockerfile in agent-v2 directory
|
|
236
|
+
const dockerfilePath = path.join(path.dirname(path.dirname(path.dirname(agentPath))), 'agent-v2', 'Dockerfile');
|
|
237
|
+
const buildContext = path.dirname(dockerfilePath);
|
|
238
|
+
try {
|
|
239
|
+
console.log(`Building Docker image from ${buildContext}...`);
|
|
240
|
+
const { stdout, stderr } = await execAsync(`docker build -t ${this.imageName} -f ${dockerfilePath} ${buildContext}`, { maxBuffer: 10 * 1024 * 1024 } // 10MB buffer for build output
|
|
241
|
+
);
|
|
242
|
+
if (stdout)
|
|
243
|
+
console.log(stdout);
|
|
244
|
+
if (stderr)
|
|
245
|
+
console.error(stderr);
|
|
246
|
+
console.log('Docker image built successfully');
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
throw new Error(`Failed to build Docker image: ${error instanceof Error ? error.message : String(error)}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
generateDockerRunCommand(config) {
|
|
253
|
+
const configPath = config.configPath;
|
|
254
|
+
const applicationsPath = path.join(configPath, 'applications');
|
|
255
|
+
const logsPath = path.join(configPath, 'logs');
|
|
256
|
+
// Ensure all required directories exist with proper permissions
|
|
257
|
+
try {
|
|
258
|
+
require('fs').mkdirSync(applicationsPath, { recursive: true, mode: 0o755 });
|
|
259
|
+
require('fs').mkdirSync(logsPath, { recursive: true, mode: 0o755 });
|
|
260
|
+
// Ensure parent directory also has proper permissions
|
|
261
|
+
require('fs').chmodSync(configPath, 0o755);
|
|
262
|
+
require('fs').chmodSync(applicationsPath, 0o755);
|
|
263
|
+
require('fs').chmodSync(logsPath, 0o755);
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
console.warn('Could not set directory permissions:', error);
|
|
267
|
+
// Continue anyway - entrypoint will try to fix permissions
|
|
268
|
+
}
|
|
269
|
+
// Docker socket path varies by platform
|
|
270
|
+
let dockerSocketMount = '';
|
|
271
|
+
if (this.platform === 'linux') {
|
|
272
|
+
dockerSocketMount = '-v /var/run/docker.sock:/var/run/docker.sock';
|
|
273
|
+
}
|
|
274
|
+
else if (this.platform === 'darwin') {
|
|
275
|
+
dockerSocketMount = '-v /var/run/docker.sock:/var/run/docker.sock';
|
|
276
|
+
}
|
|
277
|
+
else if (this.platform === 'win32') {
|
|
278
|
+
dockerSocketMount = '-v //var/run/docker.sock:/var/run/docker.sock';
|
|
279
|
+
}
|
|
280
|
+
// Use :z flag for SELinux systems to allow container access
|
|
281
|
+
// This is safe for non-SELinux systems (flag is ignored)
|
|
282
|
+
// For serving devices, use bridge network to prevent exposing Caddy ports externally
|
|
283
|
+
// For gateway devices, use host network for direct network access
|
|
284
|
+
const networkMode = config.deviceType === 'serving' ? 'bridge' : 'host';
|
|
285
|
+
const networkFlag = networkMode === 'bridge' ? '--network bridge' : '--network host';
|
|
286
|
+
// For serving devices on bridge network, we don't expose ports
|
|
287
|
+
// Caddy will bind to localhost (127.0.0.1) only, so ports won't be accessible externally
|
|
288
|
+
// Use system path inside container
|
|
289
|
+
const containerConfigPath = PathResolver_1.PathResolver.getSystemDataPath() + '/agent';
|
|
290
|
+
const containerConfigFile = `${containerConfigPath}/agent.config.json`;
|
|
291
|
+
// Required capabilities:
|
|
292
|
+
// - NET_ADMIN: For WireGuard interface management, IP routing, iptables
|
|
293
|
+
// - NET_BIND_SERVICE: For Caddy to bind to privileged ports (80, 443)
|
|
294
|
+
// - SYS_MODULE: Optional, for kernel module loading (may not work in containers)
|
|
295
|
+
return `docker create \\
|
|
296
|
+
--name ${this.containerName} \\
|
|
297
|
+
${networkFlag} \\
|
|
298
|
+
--cap-add NET_ADMIN \\
|
|
299
|
+
--cap-add NET_BIND_SERVICE \\
|
|
300
|
+
--restart unless-stopped \\
|
|
301
|
+
-v "${configPath}:${containerConfigPath}:z" \\
|
|
302
|
+
-v "${applicationsPath}:${containerConfigPath}/applications:z" \\
|
|
303
|
+
${dockerSocketMount} \\
|
|
304
|
+
-e NODE_ENV=production \\
|
|
305
|
+
-e EDGIBLE_CONFIG_PATH="${containerConfigPath}" \\
|
|
306
|
+
-e DEVICE_TYPE=${config.deviceType} \\
|
|
307
|
+
${this.imageName} \\
|
|
308
|
+
start --config "${containerConfigFile}"`;
|
|
309
|
+
}
|
|
310
|
+
async createServiceWrapper(config) {
|
|
311
|
+
if (this.platform === 'linux') {
|
|
312
|
+
await this.createSystemdWrapper();
|
|
313
|
+
}
|
|
314
|
+
else if (this.platform === 'darwin') {
|
|
315
|
+
await this.createLaunchdWrapper();
|
|
316
|
+
}
|
|
317
|
+
// Windows doesn't need a wrapper as Docker Desktop handles startup
|
|
318
|
+
}
|
|
319
|
+
async createSystemdWrapper() {
|
|
320
|
+
const serviceContent = `[Unit]
|
|
321
|
+
Description=Edgible Agent (Docker)
|
|
322
|
+
After=docker.service
|
|
323
|
+
Requires=docker.service
|
|
324
|
+
|
|
325
|
+
[Service]
|
|
326
|
+
Type=oneshot
|
|
327
|
+
RemainAfterExit=yes
|
|
328
|
+
ExecStart=/usr/bin/docker start ${this.containerName}
|
|
329
|
+
ExecStop=/usr/bin/docker stop ${this.containerName}
|
|
330
|
+
|
|
331
|
+
[Install]
|
|
332
|
+
WantedBy=multi-user.target
|
|
333
|
+
`;
|
|
334
|
+
try {
|
|
335
|
+
await fs.writeFile('/etc/systemd/system/edgible-agent-docker.service', serviceContent, 'utf8');
|
|
336
|
+
await execAsync('systemctl daemon-reload');
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
console.warn('Failed to create systemd wrapper service:', error);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
async createLaunchdWrapper() {
|
|
343
|
+
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
344
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
345
|
+
<plist version="1.0">
|
|
346
|
+
<dict>
|
|
347
|
+
<key>Label</key>
|
|
348
|
+
<string>com.edgible.agent.docker</string>
|
|
349
|
+
<key>ProgramArguments</key>
|
|
350
|
+
<array>
|
|
351
|
+
<string>/usr/local/bin/docker</string>
|
|
352
|
+
<string>start</string>
|
|
353
|
+
<string>${this.containerName}</string>
|
|
354
|
+
</array>
|
|
355
|
+
<key>RunAtLoad</key>
|
|
356
|
+
<true/>
|
|
357
|
+
<key>KeepAlive</key>
|
|
358
|
+
<dict>
|
|
359
|
+
<key>SuccessfulExit</key>
|
|
360
|
+
<false/>
|
|
361
|
+
</dict>
|
|
362
|
+
</dict>
|
|
363
|
+
</plist>
|
|
364
|
+
`;
|
|
365
|
+
try {
|
|
366
|
+
await fs.writeFile('/Library/LaunchDaemons/com.edgible.agent.docker.plist', plistContent, 'utf8');
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
console.warn('Failed to create launchd wrapper:', error);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async removeServiceWrapper() {
|
|
373
|
+
if (this.platform === 'linux') {
|
|
374
|
+
try {
|
|
375
|
+
await execAsync('systemctl disable edgible-agent-docker');
|
|
376
|
+
await fs.unlink('/etc/systemd/system/edgible-agent-docker.service');
|
|
377
|
+
await execAsync('systemctl daemon-reload');
|
|
378
|
+
}
|
|
379
|
+
catch {
|
|
380
|
+
// Ignore errors
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
else if (this.platform === 'darwin') {
|
|
384
|
+
try {
|
|
385
|
+
await execAsync('launchctl unload /Library/LaunchDaemons/com.edgible.agent.docker.plist');
|
|
386
|
+
await fs.unlink('/Library/LaunchDaemons/com.edgible.agent.docker.plist');
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
// Ignore errors
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
exports.DockerDaemonManager = DockerDaemonManager;
|
|
395
|
+
//# sourceMappingURL=DockerDaemonManager.js.map
|