UNPKG

@underpostnet/underpost

Version:

Underpost Platform — end-to-end CI/CD and application-delivery toolchain CLI. Covers bare metal, Kubernetes, K3s, kubeadm, LXD, container/image orchestration, secrets, databases, cron jobs, monitoring, SSH, runners, PWA + Workbox delivery, and release orc

333 lines (292 loc) 16 kB
/** * System provisioning module for Underpost CLI. * This module provides a factory for generating shell commands to provision systems based on their OS type. * It includes methods for basic system setup, user creation, timezone configuration, and keyboard layout settings. * The provisioning steps are tailored for both Ubuntu and Rocky Linux distributions, ensuring compatibility and ease of use. * @module src/cli/system.js * @namespace UnderpostSystemProvisionig */ import fs from 'fs-extra'; /** * @class UnderpostSystemProvisionig * @description A class that encapsulates the system provisioning logic for Underpost CLI. It provides a structured way to generate shell commands for provisioning systems based on their OS type, including Ubuntu and Rocky Linux. The class contains a static API object with a factory for different provisioning steps, making it easy to extend and maintain. * @memberof UnderpostSystemProvisionig */ class UnderpostSystemProvisionig { static API = { /** * @property {object} factory * @description A factory object containing functions for system provisioning based on OS type. * Each OS type (e.g., 'ubuntu') provides methods for base system setup, user creation, * timezone configuration, and keyboard layout settings. * @memberof UnderpostSystemProvisionig */ factory: { /** * @property {object} ubuntu * @description Provisioning steps for Ubuntu-based systems. * @memberof UnderpostSystemProvisionig */ ubuntu: { /** * @method base * @description Generates shell commands for basic Ubuntu system provisioning. * This includes updating package lists, installing essential build tools, * kernel modules, cloud-init, SSH server, and other core utilities. * @param {object} params - The parameters for the function. * @memberof UnderpostSystemProvisionig * @returns {string[]} An array of shell commands. */ base: () => [ // Configure APT sources for Ubuntu ports `cat <<SOURCES | tee /etc/apt/sources.list deb http://ports.ubuntu.com/ubuntu-ports noble main restricted universe multiverse deb http://ports.ubuntu.com/ubuntu-ports noble-updates main restricted universe multiverse deb http://ports.ubuntu.com/ubuntu-ports noble-security main restricted universe multiverse SOURCES`, // Update package lists and perform a full system upgrade `apt update -qq`, `apt -y full-upgrade`, // Install all essential packages in one consolidated step `DEBIAN_FRONTEND=noninteractive apt install -y build-essential xinput x11-xkb-utils usbutils uuid-runtime linux-image-generic systemd-sysv openssh-server sudo locales udev util-linux iproute2 netplan.io ca-certificates curl wget chrony apt-utils tzdata kmod keyboard-configuration console-setup iputils-ping`, // Ensure systemd is the init system `ln -sf /lib/systemd/systemd /sbin/init`, // Clean up `apt-get clean`, ], /** * @method user * @description Generates shell commands for creating a root user and configuring SSH access. * This is a critical security step for initial access to the provisioned system. * @memberof UnderpostSystemProvisionig * @returns {string[]} An array of shell commands. */ user: () => [ `useradd -m -s /bin/bash -G sudo root`, // Create a root user with bash shell and sudo privileges. `echo 'root:root' | chpasswd`, // Set a default password for the root user (consider more secure methods for production). `mkdir -p /home/root/.ssh`, // Create .ssh directory for authorized keys. // Add the public SSH key to authorized_keys for passwordless login. `echo '${fs.readFileSync( `/home/dd/engine/engine-private/deploy/id_rsa.pub`, 'utf8', )}' > /home/root/.ssh/authorized_keys`, `chown -R root /home/root/.ssh`, // Set ownership for security. `chmod 700 /home/root/.ssh`, // Set permissions for the .ssh directory. `chmod 600 /home/root/.ssh/authorized_keys`, // Set permissions for authorized_keys. ], /** * @method timezone * @description Generates shell commands for configuring the system timezone and Chrony (NTP client). * Accurate time synchronization is essential for logging, security, and distributed systems. * @param {object} params - The parameters for the function. * @param {string} params.timezone - The timezone string (e.g., 'America/New_York'). * @param {string} params.chronyConfPath - The path to the Chrony configuration file. * @param {string} [alias='chrony'] - The alias for the chrony service. * @memberof UnderpostSystemProvisionig * @returns {string[]} An array of shell commands. */ timezone: ({ timezone, chronyConfPath }, alias = 'chrony') => [ `export DEBIAN_FRONTEND=noninteractive`, // Set non-interactive mode for Debian packages. `ln -fs /usr/share/zoneinfo/${timezone} /etc/localtime`, // Symlink timezone. `sudo dpkg-reconfigure --frontend noninteractive tzdata`, // Reconfigure timezone data. `sudo timedatectl set-timezone ${timezone}`, // Set timezone using timedatectl. `sudo timedatectl set-ntp true`, // Enable NTP synchronization. // Write the Chrony configuration file. `echo ' # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). # pool 2.pool.ntp.org iburst server ${process.env.MAAS_NTP_SERVER} iburst # Record the rate at which the system clock gains/losses time. driftfile /var/lib/chrony/drift # Allow the system clock to be stepped in the first three updates # if its offset is larger than 1 second. makestep 1.0 3 # Enable kernel synchronization of the real-time clock (RTC). rtcsync # Enable hardware timestamping on all interfaces that support it. #hwtimestamp * # Increase the minimum number of selectable sources required to adjust # the system clock. #minsources 2 # Allow NTP client access from local network. #allow 192.168.0.0/16 # Serve time even if not synchronized to a time source. #local stratum 10 # Specify file containing keys for NTP authentication. keyfile /etc/chrony.keys # Get TAI-UTC offset and leap seconds from the system tz database. leapsectz right/UTC # Specify directory for log files. logdir /var/log/chrony # Select which information is logged. #log measurements statistics tracking ' > ${chronyConfPath}`, `systemctl stop ${alias}`, // Stop Chrony service before reconfiguring. // Enable, restart, and check status of Chrony service. `sudo systemctl enable --now ${alias}`, `sudo systemctl restart ${alias}`, // Wait for chrony to synchronize `echo "Waiting for chrony to synchronize..."`, `for i in {1..30}; do chronyc tracking | grep -q "Leap status : Normal" && break || sleep 2; done`, `sudo systemctl status ${alias}`, // Verify Chrony synchronization. `chronyc sources`, `chronyc tracking`, `chronyc sourcestats -v`, // Display source statistics. `timedatectl status`, // Display current time and date settings. ], /** * @method keyboard * @description Generates shell commands for configuring the keyboard layout. * This ensures correct input behavior on the provisioned system. * @param {string} [keyCode='en'] - The keyboard layout code (e.g., 'en', 'es'). * @memberof UnderpostSystemProvisionig * @returns {string[]} An array of shell commands. */ keyboard: (keyCode = 'en') => [ `sudo locale-gen en_US.UTF-8`, `sudo update-locale LANG=en_US.UTF-8`, `sudo sed -i 's/XKBLAYOUT="us"/XKBLAYOUT="${keyCode}"/' /etc/default/keyboard`, `sudo dpkg-reconfigure --frontend noninteractive keyboard-configuration`, `sudo systemctl restart keyboard-setup.service`, ], }, /** * @property {object} rocky * @description Provisioning steps for Rocky Linux-based systems. * @memberof UnderpostSystemProvisionig */ rocky: { /** * @method base * @description Generates shell commands for basic Rocky Linux system provisioning. * This includes installing Node.js, npm, and underpost CLI tools. * @param {object} params - The parameters for the function. * @memberof UnderpostSystemProvisionig * @returns {string[]} An array of shell commands. */ base: () => [ // Update system and install EPEL repository `dnf -y update`, `dnf -y install epel-release`, // Install essential system tools (avoiding duplicates from container packages) `dnf -y install --allowerasing bzip2 openssh-server nano vim-enhanced less openssl-devel git gnupg2 libnsl perl`, `dnf clean all`, // Install Node.js `curl -fsSL https://rpm.nodesource.com/setup_24.x | bash -`, `dnf install -y nodejs`, `dnf clean all`, // Verify Node.js and npm versions `node --version`, `npm --version`, // Install underpost ci/cd cli `npm install -g underpost`, `underpost --version`, ], /** * @method user * @description Generates shell commands for creating a root user and configuring SSH access on Rocky Linux. * This is a critical security step for initial access to the provisioned system. * @memberof UnderpostSystemProvisionig * @returns {string[]} An array of shell commands. */ user: () => [ `useradd -m -s /bin/bash -G wheel root`, // Create a root user with bash shell and wheel group (sudo on RHEL) `echo 'root:root' | chpasswd`, // Set a default password for the root user `mkdir -p /home/root/.ssh`, // Create .ssh directory for authorized keys // Add the public SSH key to authorized_keys for passwordless login `echo '${fs.readFileSync( `/home/dd/engine/engine-private/deploy/id_rsa.pub`, 'utf8', )}' > /home/root/.ssh/authorized_keys`, `chown -R root:root /home/root/.ssh`, // Set ownership for security `chmod 700 /home/root/.ssh`, // Set permissions for the .ssh directory `chmod 600 /home/root/.ssh/authorized_keys`, // Set permissions for authorized_keys ], /** * @method timezone * @description Generates shell commands for configuring the system timezone on Rocky Linux. * @param {object} params - The parameters for the function. * @param {string} params.timezone - The timezone string (e.g., 'America/Santiago'). * @param {string} params.chronyConfPath - The path to the Chrony configuration file (optional). * @memberof UnderpostSystemProvisionig * @returns {string[]} An array of shell commands. */ timezone: ({ timezone, chronyConfPath = '/etc/chrony.conf' }) => [ // Set system timezone using both methods (for chroot and running system) `ln -sf /usr/share/zoneinfo/${timezone} /etc/localtime`, `echo '${timezone}' > /etc/timezone`, `timedatectl set-timezone ${timezone} 2>/dev/null`, // Configure chrony with local NTP server and common NTP pools `echo '# Local NTP server' > ${chronyConfPath}`, `echo 'server 192.168.1.1 iburst prefer' >> ${chronyConfPath}`, `echo '' >> ${chronyConfPath}`, `echo '# Fallback public NTP servers' >> ${chronyConfPath}`, `echo 'server 0.pool.ntp.org iburst' >> ${chronyConfPath}`, `echo 'server 1.pool.ntp.org iburst' >> ${chronyConfPath}`, `echo 'server 2.pool.ntp.org iburst' >> ${chronyConfPath}`, `echo 'server 3.pool.ntp.org iburst' >> ${chronyConfPath}`, `echo '' >> ${chronyConfPath}`, `echo '# Configuration' >> ${chronyConfPath}`, `echo 'driftfile /var/lib/chrony/drift' >> ${chronyConfPath}`, `echo 'makestep 1.0 3' >> ${chronyConfPath}`, `echo 'rtcsync' >> ${chronyConfPath}`, `echo 'logdir /var/log/chrony' >> ${chronyConfPath}`, // Enable chronyd to start on boot `systemctl enable chronyd 2>/dev/null`, // Create systemd link for boot (works in chroot) `mkdir -p /etc/systemd/system/multi-user.target.wants`, `ln -sf /usr/lib/systemd/system/chronyd.service /etc/systemd/system/multi-user.target.wants/chronyd.service 2>/dev/null`, // Start chronyd if systemd is running `systemctl start chronyd 2>/dev/null`, // Restart chronyd to apply configuration `systemctl restart chronyd 2>/dev/null`, // Force immediate time synchronization (only if chronyd is running) `chronyc makestep 2>/dev/null`, // Verify timezone configuration `ls -l /etc/localtime`, `cat /etc/timezone || echo 'No /etc/timezone file'`, `timedatectl status 2>/dev/null || echo 'Timezone set to ${timezone} (timedatectl not available in chroot)'`, `chronyc tracking 2>/dev/null || echo 'Chrony configured but not running (will start on boot)'`, ], /** * @method keyboard * @description Generates shell commands for configuring the keyboard layout on Rocky Linux. * This uses localectl to set the keyboard layout for both console and X11. * @param {string} [keyCode='us'] - The keyboard layout code (e.g., 'us', 'es'). * @memberof UnderpostSystemProvisionig * @returns {string[]} An array of shell commands. */ keyboard: (keyCode = 'us') => [ // Configure vconsole.conf for console keyboard layout (persistent) `echo 'KEYMAP=${keyCode}' > /etc/vconsole.conf`, `echo 'FONT=latarcyrheb-sun16' >> /etc/vconsole.conf`, // Configure locale.conf for system locale `echo 'LANG=en_US.UTF-8' > /etc/locale.conf`, `echo 'LC_ALL=en_US.UTF-8' >> /etc/locale.conf`, // Set keyboard layout using localectl (works if systemd is running) `localectl set-locale LANG=en_US.UTF-8 2>/dev/null`, `localectl set-keymap ${keyCode} 2>/dev/null`, `localectl set-x11-keymap ${keyCode} 2>/dev/null`, // Configure X11 keyboard layout file directly `mkdir -p /etc/X11/xorg.conf.d`, `echo 'Section "InputClass"' > /etc/X11/xorg.conf.d/00-keyboard.conf`, `echo ' Identifier "system-keyboard"' >> /etc/X11/xorg.conf.d/00-keyboard.conf`, `echo ' MatchIsKeyboard "on"' >> /etc/X11/xorg.conf.d/00-keyboard.conf`, `echo ' Option "XkbLayout" "${keyCode}"' >> /etc/X11/xorg.conf.d/00-keyboard.conf`, `echo 'EndSection' >> /etc/X11/xorg.conf.d/00-keyboard.conf`, // Load the keymap immediately (if not in chroot) `loadkeys ${keyCode} 2>/dev/null || echo 'Keymap ${keyCode} configured (loadkeys not available in chroot)'`, // Verify configuration `echo 'Keyboard configuration files:'`, `cat /etc/vconsole.conf`, `cat /etc/locale.conf`, `cat /etc/X11/xorg.conf.d/00-keyboard.conf 2>/dev/null || echo 'X11 config created'`, `localectl status 2>/dev/null || echo 'Keyboard layout set to ${keyCode} (localectl not available in chroot)'`, ], }, }, }; } export default UnderpostSystemProvisionig;