111 lines
3.0 KiB
TypeScript
Executable File
111 lines
3.0 KiB
TypeScript
Executable File
import { $ } from "bun"
|
|
import { writeFileSync } from "fs"
|
|
|
|
console.log(`
|
|
==========================================
|
|
Phone Setup Bootstrap
|
|
==========================================
|
|
`)
|
|
|
|
// Check if running as root
|
|
if (process.getuid && process.getuid() !== 0) {
|
|
console.error("Please run with sudo: sudo bun bootstrap.ts [install-dir]")
|
|
console.error("Or use full path: sudo ~/.bun/bin/bun bootstrap.ts [install-dir]")
|
|
process.exit(1)
|
|
}
|
|
|
|
// Get install directory from argument or use default
|
|
const INSTALL_DIR = process.argv[2] || "/home/corey/phone"
|
|
const AP_SERVICE_FILE = "/etc/systemd/system/phone-ap.service"
|
|
const WEB_SERVICE_FILE = "/etc/systemd/system/phone-web.service"
|
|
|
|
console.log(`Install directory: ${INSTALL_DIR}`)
|
|
|
|
console.log("\nStep 1: Ensuring directory exists...")
|
|
await $`mkdir -p ${INSTALL_DIR}`
|
|
console.log(`✓ Directory ready: ${INSTALL_DIR}`)
|
|
|
|
console.log("\nStep 2: Installing dependencies...")
|
|
await $`cd ${INSTALL_DIR} && bun install`
|
|
console.log(`✓ Dependencies installed`)
|
|
|
|
console.log("\nStep 3: Installing systemd services...")
|
|
// Find where bun is installed
|
|
const bunPath = await $`which bun`
|
|
.quiet()
|
|
.nothrow()
|
|
.text()
|
|
.then((p) => p.trim())
|
|
if (!bunPath) {
|
|
console.error("Error: bun not found in PATH. Please ensure bun is available system-wide.")
|
|
process.exit(1)
|
|
}
|
|
console.log(`Using bun at: ${bunPath}`)
|
|
|
|
// Create AP monitor service
|
|
const apServiceContent = `[Unit]
|
|
Description=Phone WiFi AP Monitor
|
|
After=network.target
|
|
Before=phone-web.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=${bunPath} ${INSTALL_DIR}/services/ap-monitor.ts
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
`
|
|
writeFileSync(AP_SERVICE_FILE, apServiceContent, "utf8")
|
|
console.log("✓ Created phone-ap.service")
|
|
|
|
// Create web server service
|
|
const webServiceContent = `[Unit]
|
|
Description=Phone Web Server
|
|
After=network.target phone-ap.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=${bunPath} ${INSTALL_DIR}/services/server/server.tsx
|
|
WorkingDirectory=${INSTALL_DIR}
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
`
|
|
writeFileSync(WEB_SERVICE_FILE, webServiceContent, "utf8")
|
|
console.log("✓ Created phone-web.service")
|
|
|
|
await $`systemctl daemon-reload`
|
|
await $`systemctl enable phone-ap.service`
|
|
await $`systemctl enable phone-web.service`
|
|
console.log("✓ Services enabled")
|
|
|
|
console.log("\nStep 4: Starting the services...")
|
|
await $`systemctl start phone-ap.service`
|
|
await $`systemctl start phone-web.service`
|
|
console.log("✓ Services started")
|
|
|
|
console.log(`
|
|
==========================================
|
|
✓ Bootstrap complete!
|
|
==========================================
|
|
|
|
Both services are now running and will start automatically on boot:
|
|
- phone-ap.service: Monitors WiFi and manages AP
|
|
- phone-web.service: Web server for configuration
|
|
|
|
How it works:
|
|
- If connected to WiFi: Access at http://phone.local
|
|
- If NOT connected: WiFi AP "phone-setup" will start automatically
|
|
Connect to the AP at the same address http://phone.local
|
|
|
|
To check status use ./cli
|
|
`)
|