diff --git a/changelog.md b/changelog.md index a82b01b..5cfa6bf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2026-03-16 - 1.14.0 - feat(daemon) +auto-install Docker and initialize Swarm during daemon service setup + +- Adds a Docker availability check before installing the Onebox daemon service +- Installs Docker automatically when it is missing using the standard installation script +- Attempts to initialize Docker Swarm after installation and handles already-initialized environments gracefully + ## 2026-03-16 - 1.13.17 - fix(ci) remove forced container image pulling from Gitea workflow jobs diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 84a9ed8..6ea3c3e 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/onebox', - version: '1.13.17', + version: '1.14.0', description: 'Self-hosted container platform with automatic SSL and DNS - a mini Heroku for single servers' } diff --git a/ts/classes/daemon.ts b/ts/classes/daemon.ts index a8d3c67..d043ed3 100644 --- a/ts/classes/daemon.ts +++ b/ts/classes/daemon.ts @@ -46,6 +46,59 @@ export class OneboxDaemon { } } + /** + * Ensure Docker is installed, installing it if necessary + */ + private async ensureDocker(): Promise { + try { + const cmd = new Deno.Command('docker', { + args: ['--version'], + stdout: 'piped', + stderr: 'piped', + }); + const result = await cmd.output(); + if (result.success) { + const version = new TextDecoder().decode(result.stdout).trim(); + logger.info(`Docker found: ${version}`); + return; + } + } catch { + // docker command not found + } + + logger.info('Docker not found. Installing Docker...'); + const installCmd = new Deno.Command('bash', { + args: ['-c', 'curl -fsSL https://get.docker.com | sh'], + stdin: 'inherit', + stdout: 'inherit', + stderr: 'inherit', + }); + const installResult = await installCmd.output(); + if (!installResult.success) { + throw new Error('Failed to install Docker. Please install it manually: curl -fsSL https://get.docker.com | sh'); + } + logger.success('Docker installed successfully'); + + // Initialize Docker Swarm + logger.info('Initializing Docker Swarm...'); + const swarmCmd = new Deno.Command('docker', { + args: ['swarm', 'init'], + stdout: 'piped', + stderr: 'piped', + }); + const swarmResult = await swarmCmd.output(); + if (swarmResult.success) { + logger.success('Docker Swarm initialized'); + } else { + const stderr = new TextDecoder().decode(swarmResult.stderr); + if (stderr.includes('already part of a swarm')) { + logger.info('Docker Swarm already initialized'); + } else { + logger.warn(`Docker Swarm init warning: ${stderr.trim()}`); + } + } + } + /** * Install systemd service */ @@ -53,6 +106,9 @@ export class OneboxDaemon { try { logger.info('Installing Onebox daemon service...'); + // Ensure Docker is installed + await this.ensureDocker(); + // Initialize smartdaemon if needed if (!this.smartdaemon) { this.smartdaemon = new plugins.smartdaemon.SmartDaemon(); diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 84a9ed8..6ea3c3e 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/onebox', - version: '1.13.17', + version: '1.14.0', description: 'Self-hosted container platform with automatic SSL and DNS - a mini Heroku for single servers' }