diff --git a/.forgejo/workflows/botserver.yaml b/.forgejo/workflows/botserver.yaml index 300df4596..07bbd7e1a 100644 --- a/.forgejo/workflows/botserver.yaml +++ b/.forgejo/workflows/botserver.yaml @@ -80,7 +80,7 @@ jobs: - name: Build debug working-directory: workspace run: | - cargo build -p botserver -p botui -j 8 2>&1 | tee /tmp/build.log + cargo build -p botserver -p botui --features botui/embed-ui -j 8 2>&1 | tee /tmp/build.log ls -lh target/debug/botserver ls -lh target/debug/botui sccache --show-stats || true diff --git a/scripts/install-dependencies.sh b/scripts/install-dependencies.sh deleted file mode 100755 index ef8489e7b..000000000 --- a/scripts/install-dependencies.sh +++ /dev/null @@ -1,171 +0,0 @@ -#!/bin/bash -# -# install-dependencies.sh -# Installs all runtime dependencies required to run the botserver binary -# -# Usage: sudo ./install-dependencies.sh -# -# This script must be run on the HOST system (not inside a container) -# before running botserver for the first time. -# - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -echo -e "${GREEN}========================================${NC}" -echo -e "${GREEN} botserver Dependency Installer${NC}" -echo -e "${GREEN}========================================${NC}" -echo "" - -# Check if running as root -if [ "$EUID" -ne 0 ]; then - echo -e "${RED}Error: This script must be run as root (use sudo)${NC}" - exit 1 -fi - -# Detect OS -if [ -f /etc/os-release ]; then - . /etc/os-release - OS=$ID - VERSION=$VERSION_ID -else - echo -e "${RED}Error: Cannot detect operating system${NC}" - exit 1 -fi - -echo -e "${YELLOW}Detected OS: $OS $VERSION${NC}" -echo "" - -install_debian_ubuntu() { - echo -e "${GREEN}Installing dependencies for Debian/Ubuntu...${NC}" - - apt-get update - - # Runtime libraries for botserver binary - apt-get install -y \ - libpq5 \ - libpq-dev \ - libssl3 \ - liblzma5 \ - zlib1g \ - ca-certificates \ - curl \ - wget \ - libclang-dev \ - pkg-config - - # LXC/LXD for container management (optional but recommended) - echo "" - echo -e "${YELLOW}Installing LXD for container support...${NC}" - apt-get install -y snapd || true - snap install lxd || apt-get install -y lxd || true - - # Initialize LXD if not already done - if command -v lxd &> /dev/null; then - if ! lxc list &> /dev/null 2>&1; then - echo -e "${YELLOW}Initializing LXD...${NC}" - lxd init --auto || true - fi - fi - - echo -e "${GREEN}Debian/Ubuntu dependencies installed successfully!${NC}" -} - -install_fedora_rhel() { - echo -e "${GREEN}Installing dependencies for Fedora/RHEL...${NC}" - - dnf install -y \ - libpq \ - openssl-libs \ - xz-libs \ - zlib \ - ca-certificates \ - curl \ - wget - - # LXC for container management - dnf install -y lxc lxc-templates || true - - echo -e "${GREEN}Fedora/RHEL dependencies installed successfully!${NC}" -} - -install_arch() { - echo -e "${GREEN}Installing dependencies for Arch Linux...${NC}" - - pacman -Sy --noconfirm \ - postgresql-libs \ - openssl \ - xz \ - zlib \ - ca-certificates \ - curl \ - wget \ - lxc - - echo -e "${GREEN}Arch Linux dependencies installed successfully!${NC}" -} - -install_alpine() { - echo -e "${GREEN}Installing dependencies for Alpine Linux...${NC}" - - apk add --no-cache \ - libpq \ - openssl \ - xz-libs \ - zlib \ - ca-certificates \ - curl \ - wget \ - lxc - - echo -e "${GREEN}Alpine Linux dependencies installed successfully!${NC}" -} - -# Install based on detected OS -case $OS in - ubuntu|debian|linuxmint|pop) - install_debian_ubuntu - ;; - fedora|rhel|centos|rocky|almalinux) - install_fedora_rhel - ;; - arch|manjaro) - install_arch - ;; - alpine) - install_alpine - ;; - *) - echo -e "${RED}Unsupported operating system: $OS${NC}" - echo "" - echo "Please manually install the following libraries:" - echo " - libpq (PostgreSQL client library)" - echo " - libssl (OpenSSL)" - echo " - liblzma (XZ compression)" - echo " - zlib (compression)" - echo " - LXC/LXD (for container support)" - exit 1 - ;; -esac - -echo "" -echo -e "${GREEN}========================================${NC}" -echo -e "${GREEN} Dependencies installed successfully!${NC}" -echo -e "${GREEN}========================================${NC}" -echo "" -echo "You can now run botserver:" -echo "" -echo " ./botserver" -echo "" -echo "Or install components in containers:" -echo "" -echo " ./botserver install vault --container --tenant mycompany" -echo " ./botserver install vector_db --container --tenant mycompany" -echo "" -echo -e "${YELLOW}Note: Container commands must be run from the HOST system.${NC}" -echo "" diff --git a/scripts/utils/disk-size.md b/scripts/utils/disk-size.md deleted file mode 100644 index b7d3a5455..000000000 --- a/scripts/utils/disk-size.md +++ /dev/null @@ -1,6 +0,0 @@ -lxc list --format json | jq -r '.[].name' | while read container; do - echo -n "$container: " - lxc exec $container -- df -h / --output=used < /dev/null | tail -n1 -done - -du -h --max-depth=1 "." 2>/dev/null | sort -rh | head -n 50 | awk '{printf "%-10s %s\n", $1, $2}' diff --git a/scripts/utils/email-ips.sh b/scripts/utils/email-ips.sh deleted file mode 100644 index 442af3c18..000000000 --- a/scripts/utils/email-ips.sh +++ /dev/null @@ -1,8 +0,0 @@ -az network public-ip list --resource-group "$CLOUD_GROUP" \ - --query "[].{Name:name, IP:ipAddress, ReverseDNS:dnsSettings.reverseFqdn}" \ - -o table - -az network public-ip update --resource-group "$CLOUD_GROUP" - --name "pip-network-adapter-name" - --reverse-fqdn "outbound14.domain.com.br" - diff --git a/scripts/utils/fix-collabora-repo.sh b/scripts/utils/fix-collabora-repo.sh deleted file mode 100755 index e1a3c92a3..000000000 --- a/scripts/utils/fix-collabora-repo.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -# -# fix-collabora-repo.sh -# Removes broken Collabora Online repositories that may cause apt update failures -# - -if [ "$EUID" -ne 0 ]; then - echo "Please run as root" - exit 1 -fi - -echo "Removing Collabora repository configurations..." - -# Remove specific lists if they exist -rm -f /etc/apt/sources.list.d/collabora.list -rm -f /etc/apt/sources.list.d/collaboraoffice.list - -# Remove entries from other files -grep -r "collaboraoffice" /etc/apt/sources.list.d/ | cut -d: -f1 | sort | uniq | while read -r file; do - echo "Cleaning $file..." - sed -i '/collaboraoffice/d' "$file" -done - -sed -i '/collaboraoffice/d' /etc/apt/sources.list - -echo "Updating apt cache..." -apt-get update - -echo "Done." diff --git a/scripts/utils/setup-host.sh b/scripts/utils/setup-host.sh deleted file mode 100644 index ae611e8d5..000000000 --- a/scripts/utils/setup-host.sh +++ /dev/null @@ -1,6 +0,0 @@ - -# Host -sudo lxc config set core.trust_password "$LXC_TRUST_PASSWORD" - -# ALM-CI -lxc remote add bot 10.16.164.? --accept-certificate --password "$LXC_TRUST_PASSWORD" diff --git a/scripts/utils/startup.sh b/scripts/utils/startup.sh deleted file mode 100644 index e274f6a38..000000000 --- a/scripts/utils/startup.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Disable shell timeout - -sed -i '/TMOUT/d' /etc/profile /etc/bash.bashrc /etc/profile.d/* -echo 'export TMOUT=0' > /etc/profile.d/notimeout.sh -chmod +x /etc/profile.d/notimeout.sh -sed -i '/pam_exec.so/s/quiet/quiet set_timeout=0/' /etc/pam.d/sshd 2>/dev/null -source /etc/profile - diff --git a/src/core/package_manager/facade.rs b/src/core/package_manager/facade.rs index 81c250e72..9dfbd6622 100644 --- a/src/core/package_manager/facade.rs +++ b/src/core/package_manager/facade.rs @@ -12,17 +12,23 @@ use std::collections::HashMap; use std::fmt::Write as FmtWrite; use std::path::PathBuf; fn safe_lxc(args: &[&str]) -> Option { - SafeCommand::new("lxc") - .and_then(|c| c.args(args)) - .ok() - .and_then(|cmd| cmd.execute().ok()) + let mut cmd_res = SafeCommand::new("lxc").and_then(|c| c.args(args)); + + if std::path::Path::new("/tmp/lxd.sock").exists() { + cmd_res = cmd_res.and_then(|c| c.env("LXD_SOCKET", "/tmp/lxd.sock")); + } + + cmd_res.ok().and_then(|cmd| cmd.execute().ok()) } fn safe_lxd(args: &[&str]) -> Option { - SafeCommand::new("lxd") - .and_then(|c| c.args(args)) - .ok() - .and_then(|cmd| cmd.execute().ok()) + let mut cmd_res = SafeCommand::new("lxd").and_then(|c| c.args(args)); + + if std::path::Path::new("/tmp/lxd.sock").exists() { + cmd_res = cmd_res.and_then(|c| c.env("LXD_SOCKET", "/tmp/lxd.sock")); + } + + cmd_res.ok().and_then(|cmd| cmd.execute().ok()) } fn safe_tar(args: &[&str]) -> Option { @@ -1063,11 +1069,19 @@ Store credentials in Vault: .replace("{{DB_PASSWORD}}", &db_password); if target == "local" { trace!("Executing command: {}", rendered_cmd); - let output = SafeCommand::new("bash") + let mut cmd = SafeCommand::new("bash") .and_then(|c| c.arg("-c")) .and_then(|c| c.trusted_shell_script_arg(&rendered_cmd)) .and_then(|c| c.working_dir(&bin_path)) - .map_err(|e| anyhow::anyhow!("Failed to build bash command: {}", e))? + .map_err(|e| anyhow::anyhow!("Failed to build bash command: {}", e))?; + + if std::path::Path::new("/tmp/lxd.sock").exists() { + cmd = cmd + .env("LXD_SOCKET", "/tmp/lxd.sock") + .map_err(|e| anyhow::anyhow!("Failed to set env: {}", e))?; + } + + let output = cmd .execute() .with_context(|| { format!("Failed to execute command for component '{}'", component) diff --git a/src/core/package_manager/installer.rs b/src/core/package_manager/installer.rs index 80f676c4d..8e18e3e3b 100644 --- a/src/core/package_manager/installer.rs +++ b/src/core/package_manager/installer.rs @@ -766,8 +766,8 @@ impl PackageManager { ports: vec![], dependencies: vec![], - linux_packages: vec!["xclip".to_string(), "git".to_string(), "curl".to_string()], - macos_packages: vec!["git".to_string()], + linux_packages: vec![], + macos_packages: vec![], windows_packages: vec![], download_url: None, binary_name: None, @@ -1019,7 +1019,7 @@ EOF"#.to_string(), ports: vec![], dependencies: vec![], - linux_packages: vec!["sshfs".to_string(), "bridge-utils".to_string()], + linux_packages: vec![], macos_packages: vec![], windows_packages: vec![], download_url: None, @@ -1029,9 +1029,10 @@ EOF"#.to_string(), "sysctl -p".to_string(), ], post_install_cmds_linux: vec![ - "lxd init --auto".to_string(), - "lxc storage create default dir".to_string(), - "lxc profile device add default root disk path=/ pool=default".to_string(), + "lxd init --dump >/dev/null 2>&1 || lxd init --auto".to_string(), + "lxc storage show default >/dev/null 2>&1 || lxc storage create default dir".to_string(), + "lxc profile device include default root >/dev/null 2>&1 || lxc profile device add default root disk path=/ pool=default".to_string(), + "lxc profile device show default | grep lxd-sock >/dev/null 2>&1 || lxc profile device add default lxd-sock proxy connect=unix:/var/lib/lxd/unix.socket listen=unix:/tmp/lxd.sock bind=container uid=0 gid=0 mode=0660".to_string(), ], pre_install_cmds_macos: vec![], post_install_cmds_macos: vec![], diff --git a/src/security/command_guard.rs b/src/security/command_guard.rs index 1ba4fd71e..49fb5abd5 100644 --- a/src/security/command_guard.rs +++ b/src/security/command_guard.rs @@ -113,6 +113,7 @@ pub struct SafeCommand { args: Vec, working_dir: Option, allowed_paths: Vec, + envs: HashMap, } impl SafeCommand { @@ -136,6 +137,7 @@ impl SafeCommand { dirs::home_dir().unwrap_or_else(|| PathBuf::from("/")), std::env::current_dir().unwrap_or_else(|_| PathBuf::from("/")), ], + envs: HashMap::new(), }) } @@ -243,6 +245,13 @@ impl SafeCommand { self } + pub fn env(mut self, key: &str, value: &str) -> Result { + validate_argument(key)?; + validate_argument(value)?; + self.envs.insert(key.to_string(), value.to_string()); + Ok(self) + } + pub fn execute(&self) -> Result { let mut cmd = std::process::Command::new(&self.command); cmd.args(&self.args); @@ -256,6 +265,10 @@ impl SafeCommand { cmd.env("HOME", dirs::home_dir().unwrap_or_else(|| PathBuf::from("/tmp"))); cmd.env("LANG", "C.UTF-8"); + for (key, value) in &self.envs { + cmd.env(key, value); + } + cmd.output() .map_err(|e| CommandGuardError::ExecutionFailed(e.to_string())) } @@ -273,6 +286,10 @@ impl SafeCommand { cmd.env("HOME", dirs::home_dir().unwrap_or_else(|| PathBuf::from("/tmp"))); cmd.env("LANG", "C.UTF-8"); + for (key, value) in &self.envs { + cmd.env(key, value); + } + cmd.output() .map_err(|e| CommandGuardError::ExecutionFailed(e.to_string())) } @@ -290,6 +307,10 @@ impl SafeCommand { cmd.env("HOME", dirs::home_dir().unwrap_or_else(|| PathBuf::from("/tmp"))); cmd.env("LANG", "C.UTF-8"); + for (key, value) in &self.envs { + cmd.env(key, value); + } + cmd.spawn() .map_err(|e| CommandGuardError::ExecutionFailed(e.to_string())) } @@ -307,6 +328,10 @@ impl SafeCommand { cmd.env("HOME", dirs::home_dir().unwrap_or_else(|| PathBuf::from("/tmp"))); cmd.env("LANG", "C.UTF-8"); + for (key, value) in &self.envs { + cmd.env(key, value); + } + for (key, value) in envs { if validate_argument(key).is_ok() && validate_argument(value).is_ok() { cmd.env(key, value);