Lines 1-34typescript
2 * Linux service controller — installs a systemd *user* service so no sudo is
3 * required. `loginctl enable-linger` is attempted so the bot runs at boot even
6import { mkdirSync, rmSync, writeFileSync } from "node:fs";
7import { homedir, userInfo } from "node:os";
8import { join } from "node:path";
9import { runSafe } from "./platform.js";
10import type { LaunchSpec, ServiceController, ServiceResult } from "./types.js";
12const UNIT = "grok-telegram-bot.service";
14function unitPath(): string {
15 return join(homedir(), ".config", "systemd", "user", UNIT);
18export const linuxController: ServiceController = {
22 mkdirSync(join(homedir(), ".config", "systemd", "user"), { recursive: true });
23 mkdirSync(spec.logsDir, { recursive: true });
24 writeFileSync(unitPath(), unitFile(spec), "utf-8");
26 runSafe("systemctl", ["--user", "daemon-reload"]);
27 const en = runSafe("systemctl", ["--user", "enable", "--now", UNIT]);
28 if (!en.ok) return fail(`systemctl enable failed: ${en.out}`);
29 const linger = runSafe("loginctl", ["enable-linger", userInfo().username]);
MediumInstall Persistence
Source writes installer persistence such as shell profile or service configuration.
src/service/linux.tsView on unpkg · L14 30 const note = linger.ok ? " Boot-without-login enabled (linger)." : " (run `loginctl enable-linger` for boot-without-login)";
31 return ok(`Installed and started systemd user service "${UNIT}".${note}`);