diff --git a/changelog.md b/changelog.md index b113bce..18eb8e4 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # Changelog +## 2026-03-16 - 1.15.1 - fix(systemd) +move Docker installation and swarm initialization to systemd enable flow + +- Ensures Docker is installed before writing and enabling the systemd unit that depends on docker.service. +- Removes Docker auto-installation from Onebox initialization so setup happens in the service management path. + ## 2026-03-16 - 1.15.0 - feat(systemd) replace smartdaemon-based service management with native systemd commands diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 425da3d..3257991 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.15.0', + version: '1.15.1', description: 'Self-hosted container platform with automatic SSL and DNS - a mini Heroku for single servers' } diff --git a/ts/classes/onebox.ts b/ts/classes/onebox.ts index 29694fb..514ebb5 100644 --- a/ts/classes/onebox.ts +++ b/ts/classes/onebox.ts @@ -100,9 +100,6 @@ export class Onebox { // Ensure default admin user exists await this.ensureDefaultUser(); - // Ensure Docker is installed (auto-install on fresh servers) - await this.ensureDocker(); - // Initialize Docker await this.docker.init(); @@ -227,59 +224,6 @@ export class Onebox { } } - /** - * 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()}`); - } - } - } - /** * Check if Onebox is initialized */ diff --git a/ts/classes/systemd.ts b/ts/classes/systemd.ts index ce798a5..92b5bc9 100644 --- a/ts/classes/systemd.ts +++ b/ts/classes/systemd.ts @@ -36,6 +36,9 @@ export class OneboxSystemd { */ async enable(): Promise { try { + // Ensure Docker is installed before writing unit file (it requires docker.service) + await this.ensureDocker(); + // Write the unit file logger.info('Writing systemd unit file...'); await Deno.writeTextFile(SERVICE_FILE_PATH, SERVICE_UNIT_TEMPLATE); @@ -163,6 +166,59 @@ export class OneboxSystemd { } } + /** + * 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()}`); + } + } + } + /** * Run a systemctl command and return results */ diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 425da3d..3257991 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.15.0', + version: '1.15.1', description: 'Self-hosted container platform with automatic SSL and DNS - a mini Heroku for single servers' }