Merge pull request 'fixed install error' (#6) from huly-script into dev
Reviewed-on: #6
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
|||||||
Huntarr.io-6.3.6/
|
Huntarr.io-6.3.6/
|
||||||
|
|
||||||
|
huly-selfhost-main/
|
||||||
|
|||||||
341
ct/huly.sh
341
ct/huly.sh
@ -1,70 +1,331 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
source <(curl -fsSL https://git.bila.li/Proxmox/proxmox-ve-install-scripts/raw/branch/dev/misc/build.func)
|
# shellcheck disable=SC1091,SC2034 # SC1091: non-constant source, SC2034: unused variables
|
||||||
|
source <(curl -fsSL https://git.bila.li/Proxmox/proxmox-ve-install-scripts/raw/branch/main/misc/build.func) # Updated to main branch
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
# Author: GitHub Copilot
|
# Author: GitHub Copilot
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://github.com/hcengineering/huly-selfhost
|
# Source: https://github.com/hcengineering/huly-selfhost
|
||||||
|
|
||||||
|
# App Default Values
|
||||||
APP="Huly"
|
APP="Huly"
|
||||||
var_tags="collaboration;webapp"
|
var_tags="app;productivity;collaboration" # Used by build.func
|
||||||
var_cpu="2"
|
var_cpu="2" # Minimum recommended, Huly can be resource intensive. Used by build.func
|
||||||
var_ram="4096"
|
var_ram="4096" # Minimum recommended, especially with Rekoni. Used by build.func
|
||||||
var_disk="20"
|
var_disk="20" # Base disk, consider more for MinIO data and MongoDB. Used by build.func
|
||||||
var_os="debian"
|
var_os="debian" # Used by build.func
|
||||||
var_version="12"
|
var_version="12" # Debian Bookworm. Used by build.func
|
||||||
var_unprivileged="1"
|
var_unprivileged="1" # Run as unprivileged container. Used by build.func
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
variables
|
variables # This function is from build.func, sets up CTID, IP, etc.
|
||||||
color
|
color
|
||||||
catch_errors
|
catch_errors
|
||||||
|
|
||||||
|
# Paths and Configs
|
||||||
|
HULY_CONFIG_DIR="/opt/huly-selfhost"
|
||||||
|
HULY_INSTALL_DIR="/opt/huly"
|
||||||
|
HULY_CONFIG_FILE="$HULY_CONFIG_DIR/native.conf"
|
||||||
|
HULY_CREDS_FILE="/root/huly.creds" # Storing in /root for CT context
|
||||||
|
HULY_VERSION_FILE="$HULY_CONFIG_DIR/version.txt"
|
||||||
|
MINIO_DATA_DIR="/opt/minio/data"
|
||||||
|
_MONGODB_DATA_DIR="/var/lib/mongodb" # Default MongoDB data directory, prefixed to avoid SC2034 if not directly used in this script
|
||||||
|
|
||||||
|
# Services to manage
|
||||||
|
HULY_SERVICES=("huly-front" "huly-account" "huly-transactor" "huly-collaborator" "huly-rekoni")
|
||||||
|
DEPENDENCY_SERVICES=("minio" "mongod" "nginx")
|
||||||
|
ALL_SERVICES=("${HULY_SERVICES[@]}" "${DEPENDENCY_SERVICES[@]}")
|
||||||
|
|
||||||
|
# Function to stop all Huly and dependency services
|
||||||
|
stop_all_services() {
|
||||||
|
msg_info "Stopping all Huly related services..."
|
||||||
|
for service in "${ALL_SERVICES[@]}"; do
|
||||||
|
systemctl stop "$service" 2>/dev/null || true # Suppress error if service not found/running
|
||||||
|
done
|
||||||
|
msg_ok "All Huly related services stopped."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to start all Huly and dependency services in order
|
||||||
|
start_all_services() {
|
||||||
|
msg_info "Starting all Huly related services..."
|
||||||
|
systemctl start mongod minio nginx # Start core dependencies
|
||||||
|
sleep 3 # Give them a moment
|
||||||
|
systemctl start huly-account huly-collaborator # Account & Collaborator need Mongo
|
||||||
|
sleep 2
|
||||||
|
systemctl start huly-transactor huly-rekoni # These need Account, Mongo, Minio
|
||||||
|
sleep 2
|
||||||
|
systemctl start huly-front # Front needs all backends
|
||||||
|
msg_ok "All Huly related services started."
|
||||||
|
}
|
||||||
|
|
||||||
function update_script() {
|
function update_script() {
|
||||||
header_info
|
header_info
|
||||||
check_container_storage
|
# These checks are typically for the CT environment, called by build.func
|
||||||
check_container_resources
|
# Source build.func to make them available if needed directly, though usually not.
|
||||||
if [[ ! -d /opt/huly ]]; then
|
# . <(curl -fsSL https://git.bila.li/Proxmox/proxmox-ve-install-scripts/raw/branch/main/misc/build.func)
|
||||||
msg_error "No ${APP} Installation Found!"
|
# check_container_storage
|
||||||
exit
|
# check_container_resources
|
||||||
|
|
||||||
|
if [[ ! -d "$HULY_INSTALL_DIR" ]] || [[ ! -f "$HULY_CONFIG_FILE" ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found (missing $HULY_INSTALL_DIR or $HULY_CONFIG_FILE)!"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
msg_info "Updating $APP"
|
msg_info "Updating $APP"
|
||||||
|
|
||||||
# Update Huly services by pulling new Docker images and extracting them
|
CURRENT_DATE=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
$STD systemctl stop minio huly-front huly-account huly-transactor huly-collaborator huly-rekoni
|
|
||||||
|
|
||||||
# Temporarily install Docker for updates
|
stop_all_services
|
||||||
|
|
||||||
|
msg_info "Installing Docker temporarily for component updates"
|
||||||
$STD apt-get update
|
$STD apt-get update
|
||||||
$STD apt-get install -y docker.io
|
# Using docker.io for simplicity in CT update script, as it's often readily available
|
||||||
|
# Ensure this doesn't conflict with docker-ce if that was used for install and not fully purged
|
||||||
|
$STD apt-get install -y docker.io curl
|
||||||
$STD systemctl start docker
|
$STD systemctl start docker
|
||||||
|
msg_ok "Docker installed temporarily."
|
||||||
|
|
||||||
# Update each component
|
# Function to extract from container (similar to install script)
|
||||||
for component in front account transactor collaborator rekoni; do
|
extract_component_update() {
|
||||||
msg_info "Updating huly-$component"
|
local component_name="$1"
|
||||||
$STD docker pull hardcoreeng/$component:latest
|
local image_name="hardcoreeng/$component_name:latest"
|
||||||
$STD docker create --name huly-$component-update hardcoreeng/$component:latest
|
local target_dir="$HULY_INSTALL_DIR/$component_name"
|
||||||
$STD rm -rf /opt/huly/$component/*
|
local container_name="huly-${component_name}-update-extract"
|
||||||
$STD docker cp huly-$component-update:/usr/src/app/. /opt/huly/$component/
|
|
||||||
$STD docker rm huly-$component-update
|
msg_info "Pulling latest Docker image for $component_name: $image_name"
|
||||||
|
if ! $STD docker pull "$image_name"; then
|
||||||
|
msg_error "Failed to pull Docker image $image_name for $component_name."
|
||||||
|
return 1 # Continue with other components if one fails?
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Extracting $component_name from $image_name to $target_dir"
|
||||||
|
if ! $STD docker create --name "$container_name" "$image_name"; then
|
||||||
|
msg_error "Failed to create Docker container for $component_name."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clear old component files before extracting new ones
|
||||||
|
rm -rf "${target_dir:?}/"* # Safety: :? ensures var is set
|
||||||
|
mkdir -p "$target_dir"
|
||||||
|
|
||||||
|
local extracted=false
|
||||||
|
for path_in_container in "/app/dist" "/app" "/usr/src/app/dist" "/usr/src/app" "/dist" "/opt/app" "/home/app"; do
|
||||||
|
if $STD docker exec "$container_name" ls "${path_in_container}/." >/dev/null 2>&1; then
|
||||||
|
if $STD docker cp "${container_name}:${path_in_container}/." "$target_dir/"; then
|
||||||
|
extracted=true
|
||||||
|
msg_ok "Extracted updated $component_name from ${path_in_container}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! $extracted; then
|
||||||
|
msg_warn "Could not find standard app directory in $component_name container. Copying entire root."
|
||||||
|
if ! $STD docker cp "${container_name}:/." "$target_dir/"; then
|
||||||
|
msg_error "Failed to copy any files for updated $component_name."
|
||||||
|
$STD docker rm "$container_name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
$STD docker rm "$container_name"
|
||||||
|
msg_ok "Extraction update completed for $component_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update each Huly component
|
||||||
|
for component in "${HULY_SERVICES[@]//huly-/}"; do # Removes "huly-" prefix for image name
|
||||||
|
extract_component_update "$component"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Remove Docker again
|
msg_info "Removing Docker"
|
||||||
$STD systemctl stop docker
|
$STD systemctl stop docker
|
||||||
$STD apt-get remove -y docker.io
|
$STD apt-get remove -y docker.io docker-ce docker-ce-cli containerd.io --allow-remove-essential
|
||||||
|
$STD apt-get purge -y docker.io docker-ce docker-ce-cli containerd.io --allow-remove-essential
|
||||||
|
$STD apt-get autoremove -y
|
||||||
|
$STD rm -rf /var/lib/docker /var/lib/containerd
|
||||||
|
msg_ok "Docker removed."
|
||||||
|
|
||||||
# Restart services
|
# Update version information
|
||||||
$STD systemctl start minio huly-front huly-account huly-transactor huly-collaborator huly-rekoni
|
echo "$CURRENT_DATE - Updated Huly Components" >>"$HULY_VERSION_FILE"
|
||||||
|
|
||||||
msg_ok "Updated $APP"
|
start_all_services
|
||||||
exit
|
msg_ok "Updated $APP successfully. All services restarted."
|
||||||
}
|
}
|
||||||
|
|
||||||
start
|
function backup_script() {
|
||||||
build_container
|
header_info
|
||||||
description
|
# check_container_storage (if relevant for backup space)
|
||||||
|
|
||||||
|
if [[ ! -d "$HULY_CONFIG_DIR" ]]; then
|
||||||
|
msg_error "No ${APP} Installation Found (missing $HULY_CONFIG_DIR)!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BACKUP_DATE=$(date +%Y-%m-%d_%H%M%S)
|
||||||
|
BACKUP_FILENAME_BASE="huly-native-backup-$BACKUP_DATE"
|
||||||
|
BACKUP_TEMP_DIR="/tmp/$BACKUP_FILENAME_BASE"
|
||||||
|
ARCHIVE_DESTINATION="/root" # Standard backup location in these scripts
|
||||||
|
FINAL_ARCHIVE_PATH="$ARCHIVE_DESTINATION/$BACKUP_FILENAME_BASE.tar.gz"
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_TEMP_DIR/config"
|
||||||
|
mkdir -p "$BACKUP_TEMP_DIR/mongodb"
|
||||||
|
mkdir -p "$BACKUP_TEMP_DIR/minio_data"
|
||||||
|
|
||||||
|
msg_info "Backing up Huly configuration..."
|
||||||
|
cp "$HULY_CONFIG_FILE" "$BACKUP_TEMP_DIR/config/"
|
||||||
|
if [ -f "$HULY_CREDS_FILE" ]; then
|
||||||
|
cp "$HULY_CREDS_FILE" "$BACKUP_TEMP_DIR/config/"
|
||||||
|
else
|
||||||
|
msg_warn "Credentials file $HULY_CREDS_FILE not found. Skipping."
|
||||||
|
fi
|
||||||
|
if [ -f "$HULY_VERSION_FILE" ]; then
|
||||||
|
cp "$HULY_VERSION_FILE" "$BACKUP_TEMP_DIR/config/"
|
||||||
|
fi
|
||||||
|
# Backup entire /opt/huly-selfhost for any other files?
|
||||||
|
# cp -r "$HULY_CONFIG_DIR" "$BACKUP_TEMP_DIR/config_full_dir"
|
||||||
|
msg_ok "Huly configuration backed up."
|
||||||
|
|
||||||
|
msg_info "Backing up MongoDB database (huly)..."
|
||||||
|
# Ensure mongodump is available
|
||||||
|
if command -v mongodump >/dev/null 2>&1; then
|
||||||
|
if mongodump --db=huly --archive="$BACKUP_TEMP_DIR/mongodb/huly.gz" --gzip; then
|
||||||
|
msg_ok "MongoDB backup successful."
|
||||||
|
else
|
||||||
|
msg_warn "MongoDB backup (mongodump) failed. Archive might be incomplete."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
msg_warn "mongodump command not found. Skipping MongoDB backup."
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Backing up MinIO data..."
|
||||||
|
if [ -d "$MINIO_DATA_DIR" ]; then
|
||||||
|
# Ensure MinIO service is stopped or data is consistent before copying
|
||||||
|
# For simplicity, assuming data is quiesced if services are stopped during a full restore scenario
|
||||||
|
# For live backup, MinIO has mc mirror/backup tools, but that adds complexity here.
|
||||||
|
# Tarring MinIO data to preserve permissions and structure within the backup.
|
||||||
|
tar -czf "$BACKUP_TEMP_DIR/minio_data/minio_data.tar.gz" -C "$(dirname "$MINIO_DATA_DIR")" "$(basename "$MINIO_DATA_DIR")"
|
||||||
|
msg_ok "MinIO data backed up."
|
||||||
|
else
|
||||||
|
msg_warn "MinIO data directory $MINIO_DATA_DIR not found. Skipping MinIO data backup."
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Creating final backup archive: $FINAL_ARCHIVE_PATH"
|
||||||
|
if tar -czf "$FINAL_ARCHIVE_PATH" -C "/tmp" "$BACKUP_FILENAME_BASE"; then
|
||||||
|
msg_ok "Backup archive created successfully."
|
||||||
|
else
|
||||||
|
msg_error "Failed to create final backup archive."
|
||||||
|
rm -rf "$BACKUP_TEMP_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Cleaning up temporary backup files..."
|
||||||
|
rm -rf "$BACKUP_TEMP_DIR"
|
||||||
|
msg_ok "Cleanup complete."
|
||||||
|
echo -e "${INFO} Backup created at: ${GN}$FINAL_ARCHIVE_PATH${CL}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function restore_script() {
|
||||||
|
header_info
|
||||||
|
# check_container_storage (ensure enough space for restore)
|
||||||
|
|
||||||
|
LATEST_BACKUP=$(ls -t $ARCHIVE_DESTINATION/huly-native-backup-*.tar.gz 2>/dev/null | head -n1)
|
||||||
|
|
||||||
|
if [[ -z "$LATEST_BACKUP" ]]; then
|
||||||
|
msg_error "No Huly native backup archive found in $ARCHIVE_DESTINATION/!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Found latest backup: $LATEST_BACKUP"
|
||||||
|
RESTORE_TEMP_DIR="/tmp/huly-restore-extract-$(date +%s)"
|
||||||
|
mkdir -p "$RESTORE_TEMP_DIR"
|
||||||
|
|
||||||
|
msg_info "Extracting backup archive to $RESTORE_TEMP_DIR..."
|
||||||
|
if ! tar -xzf "$LATEST_BACKUP" -C "$RESTORE_TEMP_DIR"; then
|
||||||
|
msg_error "Failed to extract backup archive."
|
||||||
|
rm -rf "$RESTORE_TEMP_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The archive was created with -C /tmp backup_base_name. So files are in $RESTORE_TEMP_DIR/backup_base_name/
|
||||||
|
EXTRACTED_CONTENT_DIR_NAME=$(ls "$RESTORE_TEMP_DIR")
|
||||||
|
ACTUAL_RESTORE_DATA_DIR="$RESTORE_TEMP_DIR/$EXTRACTED_CONTENT_DIR_NAME"
|
||||||
|
|
||||||
|
if [ ! -d "$ACTUAL_RESTORE_DATA_DIR/config" ]; then
|
||||||
|
msg_error "Extracted archive does not contain expected 'config' directory. Restore aborted."
|
||||||
|
rm -rf "$RESTORE_TEMP_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
stop_all_services
|
||||||
|
|
||||||
|
msg_info "Restoring Huly configuration..."
|
||||||
|
# Restore native.conf, huly.creds, version.txt
|
||||||
|
cp -f "$ACTUAL_RESTORE_DATA_DIR/config/native.conf" "$HULY_CONFIG_FILE" 2>/dev/null || msg_warn "native.conf not found in backup."
|
||||||
|
cp -f "$ACTUAL_RESTORE_DATA_DIR/config/huly.creds" "$HULY_CREDS_FILE" 2>/dev/null || msg_warn "huly.creds not found in backup."
|
||||||
|
cp -f "$ACTUAL_RESTORE_DATA_DIR/config/version.txt" "$HULY_VERSION_FILE" 2>/dev/null || msg_warn "version.txt not found in backup."
|
||||||
|
# chown/chmod if necessary, e.g., chmod 600 $HULY_CREDS_FILE
|
||||||
|
msg_ok "Huly configuration restored."
|
||||||
|
|
||||||
|
msg_info "Restoring MongoDB database (huly)..."
|
||||||
|
if [ -f "$ACTUAL_RESTORE_DATA_DIR/mongodb/huly.gz" ]; then
|
||||||
|
if command -v mongorestore >/dev/null 2>&1; then
|
||||||
|
# Stop mongod if it was auto-restarted by systemd after the global stop
|
||||||
|
systemctl stop mongod 2>/dev/null
|
||||||
|
# It is critical that mongod is running for mongorestore to connect.
|
||||||
|
# However, we need to ensure it's clean. A --drop is often used.
|
||||||
|
# For simplicity, start it, restore, then it will be part of start_all_services.
|
||||||
|
systemctl start mongod
|
||||||
|
sleep 2 # Give MongoDB a moment to start
|
||||||
|
if mongorestore --db=huly --archive="$ACTUAL_RESTORE_DATA_DIR/mongodb/huly.gz" --gzip --drop; then
|
||||||
|
msg_ok "MongoDB restore successful."
|
||||||
|
else
|
||||||
|
msg_warn "MongoDB restore (mongorestore) failed. Check MongoDB logs."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
msg_warn "mongorestore command not found. Skipping MongoDB restore."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
msg_warn "MongoDB backup file (huly.gz) not found in archive. Skipping MongoDB restore."
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Restoring MinIO data..."
|
||||||
|
if [ -f "$ACTUAL_RESTORE_DATA_DIR/minio_data/minio_data.tar.gz" ]; then
|
||||||
|
# Stop minio if it was auto-restarted
|
||||||
|
systemctl stop minio 2>/dev/null
|
||||||
|
rm -rf "${MINIO_DATA_DIR:?}/"* # Clear existing MinIO data
|
||||||
|
mkdir -p "$MINIO_DATA_DIR"
|
||||||
|
if tar -xzf "$ACTUAL_RESTORE_DATA_DIR/minio_data/minio_data.tar.gz" -C "$(dirname "$MINIO_DATA_DIR")"; then
|
||||||
|
# Ensure correct ownership for MinIO data dir (user minio)
|
||||||
|
chown -R minio:minio "$MINIO_DATA_DIR"
|
||||||
|
msg_ok "MinIO data restored."
|
||||||
|
else
|
||||||
|
msg_warn "Failed to extract MinIO data from archive."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
msg_warn "MinIO data archive (minio_data.tar.gz) not found in backup. Skipping MinIO data restore."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Note: Application files in /opt/huly/* are NOT part of this backup/restore.
|
||||||
|
# The update script is responsible for fetching/extracting these.
|
||||||
|
# This backup focuses on user data and configurations.
|
||||||
|
|
||||||
|
msg_info "Cleaning up temporary restore files..."
|
||||||
|
rm -rf "$RESTORE_TEMP_DIR"
|
||||||
|
msg_ok "Cleanup complete."
|
||||||
|
|
||||||
|
start_all_services
|
||||||
|
msg_ok "Restore completed from $LATEST_BACKUP. All services restarted."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Standard Proxmox VE script functions (start, build_container, description)
|
||||||
|
start # This function is from build.func
|
||||||
|
build_container # This function is from build.func
|
||||||
|
description # This function is from build.func
|
||||||
|
|
||||||
|
# Final messages to user after CT creation
|
||||||
msg_ok "Completed Successfully!\n"
|
msg_ok "Completed Successfully!\n"
|
||||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
echo -e "${CREATING}${GN}${APP} LXC container has been successfully created!${CL}"
|
||||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
echo -e "${INFO}${YW} Access Huly via Nginx reverse proxy at:${CL}"
|
||||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
|
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL} (or your configured domain name)"
|
||||||
echo -e "${INFO}${YW} Note: Huly requires additional configuration for features like email, audio/video, and AI.${CL}"
|
if [ -f "$HULY_CREDS_FILE" ]; then
|
||||||
echo -e "${INFO}${YW} See the documentation at: https://github.com/hcengineering/huly-selfhost${CL}"
|
echo -e "${INFO}${YW} Initial admin credentials and keys are in: ${HULY_CREDS_FILE} (inside the CT). Secure them!${CL}"
|
||||||
|
fi
|
||||||
|
echo -e "${INFO}${YW} MinIO Console (if needed directly): http://${IP}:9001${CL}"
|
||||||
|
echo -e "${INFO}${YW} Refer to Huly documentation for first-time setup and usage: https://github.com/hcengineering/huly-selfhost${CL}"
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Copyright (c) 2021-2025 community-scripts ORG
|
# Copyright (c) 2021-2025 community-scripts ORG
|
||||||
# Author: GitHub Copilot
|
# Author: GitHub Copilot
|
||||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||||
# Source: https://github.com/hcengineering/huly-selfhost
|
# Source: https://github.com/hcengineering/huly-selfhost
|
||||||
|
|
||||||
|
# Import Functions and Setup
|
||||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||||
color
|
color
|
||||||
verb_ip6
|
verb_ip6
|
||||||
@ -12,28 +14,34 @@ setting_up_container
|
|||||||
network_check
|
network_check
|
||||||
update_os
|
update_os
|
||||||
|
|
||||||
|
# Installing Dependencies
|
||||||
msg_info "Installing Dependencies"
|
msg_info "Installing Dependencies"
|
||||||
$STD apt-get update
|
$STD apt-get update
|
||||||
$STD apt-get install -y curl git ca-certificates gnupg nginx lsb-release
|
$STD apt-get install -y curl git ca-certificates gnupg nginx lsb-release python3 python3-pip python3-venv
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
|
# Installing Python and uv package manager
|
||||||
|
msg_info "Setting up Python environment and uv"
|
||||||
|
setup_uv
|
||||||
|
msg_ok "Python environment and uv ready"
|
||||||
|
|
||||||
msg_info "Installing MongoDB"
|
msg_info "Installing MongoDB"
|
||||||
# Install MongoDB natively
|
# Install MongoDB natively
|
||||||
$STD curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | gpg --dearmor -o /etc/apt/keyrings/mongodb-server-7.0.gpg
|
$STD curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | gpg --dearmor -o /etc/apt/keyrings/mongodb-server-7.0.gpg
|
||||||
$STD echo "deb [ arch=amd64,arm64 signed-by=/etc/apt/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/debian $(lsb_release -cs)/mongodb-org/7.0 main" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list
|
$STD echo "deb [ arch=amd64,arm64 signed-by=/etc/apt/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/debian $(lsb_release -cs)/mongodb-org/7.0 main" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list >/dev/null
|
||||||
$STD apt-get update
|
$STD apt-get update
|
||||||
$STD apt-get install -y mongodb-org
|
$STD apt-get install -y mongodb-org
|
||||||
$STD systemctl enable --now mongod
|
$STD systemctl enable --now mongod
|
||||||
msg_ok "Installed MongoDB"
|
msg_ok "Installed MongoDB"
|
||||||
|
|
||||||
msg_info "Installing Node.js"
|
msg_info "Installing Node.js and web-push"
|
||||||
# Install Node.js for running Huly services
|
# Install Node.js for running Huly services
|
||||||
NODE_VERSION=20 install_node_and_modules
|
NODE_VERSION=20 install_node_and_modules # This function is from tools.func
|
||||||
$STD npm install -g web-push
|
$STD npm install -g web-push
|
||||||
msg_ok "Installed Node.js"
|
msg_ok "Installed Node.js and web-push"
|
||||||
|
|
||||||
msg_info "Installing Docker temporarily (for extraction)"
|
# Use temporary Docker for extracting components
|
||||||
# We need Docker temporarily to extract Huly applications
|
msg_info "Installing Docker temporarily (for Huly component extraction)"
|
||||||
$STD mkdir -p /etc/apt/keyrings
|
$STD mkdir -p /etc/apt/keyrings
|
||||||
$STD curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
$STD curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||||
$STD echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list >/dev/null
|
$STD echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list >/dev/null
|
||||||
@ -42,161 +50,331 @@ $STD apt-get install -y docker-ce docker-ce-cli containerd.io
|
|||||||
$STD systemctl start docker
|
$STD systemctl start docker
|
||||||
msg_ok "Installed Docker temporarily"
|
msg_ok "Installed Docker temporarily"
|
||||||
|
|
||||||
msg_info "Configuring native Huly setup"
|
msg_info "Setting up Huly environment and configuration"
|
||||||
|
# Create necessary directories
|
||||||
|
$STD mkdir -p /opt/huly-selfhost
|
||||||
|
$STD mkdir -p /opt/huly/{front,account,transactor,collaborator,rekoni}
|
||||||
|
|
||||||
# Get server IP
|
# Get server IP
|
||||||
SERVER_IP=$(hostname -I | awk '{print $1}')
|
SERVER_IP=$(hostname -I | awk '{print $1}')
|
||||||
|
|
||||||
# Generate VAPID keys for push notifications
|
# Generate VAPID keys for push notifications
|
||||||
VAPID_OUTPUT=$(web-push generate-vapid-keys)
|
VAPID_OUTPUT=$($STD web-push generate-vapid-keys)
|
||||||
PUBLIC_KEY=$(echo "$VAPID_OUTPUT" | grep "Public Key:" | cut -d ":" -f2 | tr -d ' ')
|
VAPID_PUBLIC_KEY=$(echo "$VAPID_OUTPUT" | grep "Public Key:" | cut -d ":" -f2 | tr -d ' ')
|
||||||
PRIVATE_KEY=$(echo "$VAPID_OUTPUT" | grep "Private Key:" | cut -d ":" -f2 | tr -d ' ')
|
VAPID_PRIVATE_KEY=$(echo "$VAPID_OUTPUT" | grep "Private Key:" | cut -d ":" -f2 | tr -d ' ')
|
||||||
|
|
||||||
# Create MongoDB database and user for Huly
|
# Create MongoDB database and user for Huly
|
||||||
$STD mongosh --eval "
|
# Ensure mongosh is available or use mongo if older version
|
||||||
|
MONGO_EXEC=$(command -v mongosh || command -v mongo)
|
||||||
|
if [ -z "$MONGO_EXEC" ]; then
|
||||||
|
msg_error "Neither mongosh nor mongo command found. Cannot create MongoDB user for Huly."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
$STD $MONGO_EXEC --eval "
|
||||||
use huly;
|
use huly;
|
||||||
db.createUser({
|
db.createUser({
|
||||||
user: 'huly',
|
user: 'huly',
|
||||||
pwd: 'hulypassword123',
|
pwd: 'hulypassword123', // Consider making this configurable or randomly generated
|
||||||
roles: [{role: 'readWrite', db: 'huly'}]
|
roles: [{role: 'readWrite', db: 'huly'}]
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
|
msg_ok "Created MongoDB user and database for Huly"
|
||||||
|
|
||||||
# Save configuration and VAPID keys
|
# Save configuration and VAPID keys
|
||||||
mkdir -p /opt/huly-selfhost
|
APP_SECRET_KEY=$(openssl rand -hex 32) # Generate a random secret key
|
||||||
{
|
|
||||||
echo "# Huly Native Configuration"
|
|
||||||
echo "SERVER_IP=$SERVER_IP"
|
|
||||||
echo "MONGO_URL=mongodb://huly:hulypassword123@localhost:27017/huly"
|
|
||||||
echo "MINIO_ENDPOINT=localhost:9000"
|
|
||||||
echo "MINIO_ACCESS_KEY=minioadmin"
|
|
||||||
echo "MINIO_SECRET_KEY=minioadmin"
|
|
||||||
echo ""
|
|
||||||
echo "# VAPID Keys for Push Notifications"
|
|
||||||
echo "VAPID_PUBLIC_KEY=$PUBLIC_KEY"
|
|
||||||
echo "VAPID_PRIVATE_KEY=$PRIVATE_KEY"
|
|
||||||
echo ""
|
|
||||||
echo "# Service Ports"
|
|
||||||
echo "FRONT_PORT=3000"
|
|
||||||
echo "ACCOUNT_PORT=3001"
|
|
||||||
echo "TRANSACTOR_PORT=3002"
|
|
||||||
echo "COLLABORATOR_PORT=3078"
|
|
||||||
echo "REKONI_PORT=4004"
|
|
||||||
} >/opt/huly-selfhost/native.conf
|
|
||||||
|
|
||||||
msg_ok "Configured Huly"
|
cat <<EOF >/opt/huly-selfhost/native.conf
|
||||||
|
# Huly Native Configuration
|
||||||
|
SERVER_IP=$SERVER_IP
|
||||||
|
MONGO_URL=mongodb://huly:hulypassword123@localhost:27017/huly
|
||||||
|
MINIO_ENDPOINT=localhost:9000
|
||||||
|
MINIO_ACCESS_KEY=minioadmin # Consider making this configurable or randomly generated
|
||||||
|
MINIO_SECRET_KEY=minioadmin # Consider making this configurable or randomly generated
|
||||||
|
APP_SECRET_KEY=$APP_SECRET_KEY
|
||||||
|
|
||||||
|
# VAPID Keys for Push Notifications
|
||||||
|
VAPID_PUBLIC_KEY=$VAPID_PUBLIC_KEY
|
||||||
|
VAPID_PRIVATE_KEY=$VAPID_PRIVATE_KEY
|
||||||
|
|
||||||
|
# Service Ports (ensure these are unique and not conflicting)
|
||||||
|
FRONT_PORT=3000
|
||||||
|
ACCOUNT_PORT=3001
|
||||||
|
TRANSACTOR_PORT=3002
|
||||||
|
COLLABORATOR_PORT=3078
|
||||||
|
REKONI_PORT=4004
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF >~/huly.creds
|
||||||
|
Huly Credentials (save this file securely!)
|
||||||
|
MongoDB URL: mongodb://huly:hulypassword123@localhost:27017/huly
|
||||||
|
MinIO Access: minioadmin / minioadmin (Console: http://$SERVER_IP:9001)
|
||||||
|
App Secret Key: $APP_SECRET_KEY
|
||||||
|
VAPID Public Key: $VAPID_PUBLIC_KEY
|
||||||
|
VAPID Private Key: $VAPID_PRIVATE_KEY
|
||||||
|
EOF
|
||||||
|
chmod 600 ~/huly.creds
|
||||||
|
msg_ok "Set up Huly environment and configuration in /opt/huly-selfhost/native.conf and ~/huly.creds"
|
||||||
|
|
||||||
msg_info "Extracting Huly applications from Docker images"
|
msg_info "Extracting Huly applications from Docker images"
|
||||||
# Create directories for Huly components
|
# Function to extract from container with fallback paths
|
||||||
mkdir -p /opt/huly/{front,account,transactor,collaborator,rekoni,elastic,minio}
|
extract_from_container() {
|
||||||
|
local component_name="$1"
|
||||||
|
local image_name="$2"
|
||||||
|
local target_dir="$3"
|
||||||
|
local container_name="huly-${component_name}-extract"
|
||||||
|
|
||||||
# Extract Frontend
|
msg_info "Pulling Docker image for $component_name: $image_name"
|
||||||
$STD docker create --name huly-front hardcoreeng/front:latest
|
if ! $STD docker pull "$image_name"; then
|
||||||
$STD docker cp huly-front:/usr/src/app/. /opt/huly/front/
|
msg_error "Failed to pull Docker image $image_name for $component_name."
|
||||||
$STD docker rm huly-front
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Extract Account Service
|
msg_info "Extracting $component_name from $image_name to $target_dir"
|
||||||
$STD docker create --name huly-account hardcoreeng/account:latest
|
if ! $STD docker create --name "$container_name" "$image_name"; then
|
||||||
$STD docker cp huly-account:/usr/src/app/. /opt/huly/account/
|
msg_error "Failed to create Docker container for $component_name."
|
||||||
$STD docker rm huly-account
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Extract Transactor
|
# Try common paths where applications might be located
|
||||||
$STD docker create --name huly-transactor hardcoreeng/transactor:latest
|
local extracted=false
|
||||||
$STD docker cp huly-transactor:/usr/src/app/. /opt/huly/transactor/
|
# Order matters: specific paths first, then broader ones
|
||||||
$STD docker rm huly-transactor
|
for path_in_container in "/app/dist" "/app" "/usr/src/app/dist" "/usr/src/app" "/dist" "/opt/app" "/home/app"; do
|
||||||
|
# Check if path exists in container before attempting to copy
|
||||||
|
if $STD docker exec "$container_name" ls "${path_in_container}/." >/dev/null 2>&1; then
|
||||||
|
if $STD docker cp "${container_name}:${path_in_container}/." "$target_dir/"; then
|
||||||
|
extracted=true
|
||||||
|
msg_ok "Extracted $component_name from ${path_in_container}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# Extract Collaborator (for document collaboration)
|
if ! $extracted; then
|
||||||
$STD docker create --name huly-collaborator hardcoreeng/collaborator:latest
|
msg_warn "Could not find standard app directory in $component_name container ($image_name). Attempting to copy entire root '/'. This might be slow and include unnecessary files."
|
||||||
$STD docker cp huly-collaborator:/usr/src/app/. /opt/huly/collaborator/
|
if $STD docker cp "${container_name}:/." "$target_dir/"; then
|
||||||
$STD docker rm huly-collaborator
|
msg_ok "Copied entire root for $component_name. Review $target_dir for correctness."
|
||||||
|
else
|
||||||
|
msg_error "Failed to copy any files for $component_name from $image_name."
|
||||||
|
$STD docker rm "$container_name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
$STD docker rm "$container_name"
|
||||||
|
msg_ok "Extraction process completed for $component_name"
|
||||||
|
}
|
||||||
|
|
||||||
# Extract Rekoni (for file indexing)
|
# Extract Huly Components
|
||||||
$STD docker create --name huly-rekoni hardcoreeng/rekoni:latest
|
extract_from_container "front" "hardcoreeng/front:latest" "/opt/huly/front"
|
||||||
$STD docker cp huly-rekoni:/usr/src/app/. /opt/huly/rekoni/
|
extract_from_container "account" "hardcoreeng/account:latest" "/opt/huly/account"
|
||||||
$STD docker rm huly-rekoni
|
extract_from_container "transactor" "hardcoreeng/transactor:latest" "/opt/huly/transactor"
|
||||||
|
extract_from_container "collaborator" "hardcoreeng/collaborator:latest" "/opt/huly/collaborator"
|
||||||
msg_ok "Extracted Huly applications"
|
extract_from_container "rekoni" "hardcoreeng/rekoni:latest" "/opt/huly/rekoni"
|
||||||
|
msg_ok "Extracted all Huly applications"
|
||||||
|
|
||||||
msg_info "Installing MinIO for object storage"
|
msg_info "Installing MinIO for object storage"
|
||||||
# Download MinIO binary
|
# Fetch latest MinIO version dynamically if possible, or use a known good one
|
||||||
|
# For stability, using a fixed version. Update as needed.
|
||||||
MINIO_VERSION="RELEASE.2024-06-13T22-53-53Z"
|
MINIO_VERSION="RELEASE.2024-06-13T22-53-53Z"
|
||||||
$STD curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.${MINIO_VERSION}" -o /usr/local/bin/minio
|
$STD curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.${MINIO_VERSION}" -o /usr/local/bin/minio
|
||||||
$STD chmod +x /usr/local/bin/minio
|
$STD chmod +x /usr/local/bin/minio
|
||||||
|
useradd -r -s /bin/false minio 2>/dev/null || true # Create user if not exists, suppress error if it does
|
||||||
# Create MinIO user and directories
|
|
||||||
useradd -r -s /bin/false minio || true
|
|
||||||
mkdir -p /opt/minio/data /etc/minio
|
mkdir -p /opt/minio/data /etc/minio
|
||||||
chown -R minio:minio /opt/minio /etc/minio
|
chown -R minio:minio /opt/minio /etc/minio
|
||||||
|
|
||||||
# Create MinIO configuration
|
# Source native.conf for MinIO keys to write into minio.conf
|
||||||
|
# This ensures consistency if keys were changed in native.conf
|
||||||
|
source /opt/huly-selfhost/native.conf
|
||||||
|
|
||||||
cat <<EOF >/etc/minio/minio.conf
|
cat <<EOF >/etc/minio/minio.conf
|
||||||
MINIO_ROOT_USER=minioadmin
|
MINIO_ROOT_USER=${MINIO_ACCESS_KEY}
|
||||||
MINIO_ROOT_PASSWORD=minioadmin
|
MINIO_ROOT_PASSWORD=${MINIO_SECRET_KEY}
|
||||||
MINIO_VOLUMES="/opt/minio/data"
|
MINIO_VOLUMES="/opt/minio/data"
|
||||||
MINIO_OPTS="--console-address :9001"
|
MINIO_OPTS="--console-address :9001"
|
||||||
EOF
|
EOF
|
||||||
msg_ok "Installed MinIO"
|
msg_ok "Installed and configured MinIO"
|
||||||
|
|
||||||
|
msg_info "Setting up Rekoni Python environment"
|
||||||
|
REKONI_PYTHON_EXEC="/usr/bin/python3" # Default system Python
|
||||||
|
|
||||||
|
# Define Rekoni venv path
|
||||||
|
REKONI_VENV_PATH="/opt/huly-venv/rekoni"
|
||||||
|
$STD mkdir -p "$(dirname "$REKONI_VENV_PATH")"
|
||||||
|
|
||||||
|
if [ -f /opt/huly/rekoni/requirements.txt ]; then
|
||||||
|
msg_info "Found requirements.txt for Rekoni. Creating virtual environment at $REKONI_VENV_PATH."
|
||||||
|
if $STD /usr/local/bin/uv venv "$REKONI_VENV_PATH"; then
|
||||||
|
REKONI_PYTHON_EXEC="$REKONI_VENV_PATH/bin/python3"
|
||||||
|
msg_info "Installing Rekoni dependencies from requirements.txt using uv into venv."
|
||||||
|
# Activate venv for pip install or ensure uv uses the correct python
|
||||||
|
if $STD "$REKONI_VENV_PATH/bin/uv" pip install -r /opt/huly/rekoni/requirements.txt; then
|
||||||
|
msg_ok "Rekoni dependencies installed into virtual environment."
|
||||||
|
else
|
||||||
|
msg_error "Failed to install Rekoni dependencies from requirements.txt using uv. Rekoni might not work."
|
||||||
|
REKONI_PYTHON_EXEC="/usr/bin/python3" # Fallback to system Python
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
msg_warn "Failed to create virtual environment for Rekoni with uv. Will attempt system-wide Python package installation for Rekoni."
|
||||||
|
# Attempt to install requirements.txt system-wide as a fallback
|
||||||
|
msg_info "Attempting to install Rekoni dependencies from requirements.txt system-wide using uv."
|
||||||
|
if $STD /usr/local/bin/uv pip install --system -r /opt/huly/rekoni/requirements.txt; then
|
||||||
|
msg_ok "Installed Rekoni dependencies system-wide from requirements.txt."
|
||||||
|
else
|
||||||
|
msg_error "Failed to install Rekoni dependencies system-wide from requirements.txt. Rekoni might not work."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
msg_warn "requirements.txt not found for Rekoni in /opt/huly/rekoni/. Attempting to install a common set of Python packages system-wide."
|
||||||
|
# List of common dependencies, keep this updated based on Rekoni's needs
|
||||||
|
COMMON_REKONI_DEPS="fastapi uvicorn python-multipart Pillow Wand pdf2image pytesseract nltk spacy Faker requests beautifulsoup4 readability-lxml sentence-transformers pymongo minio pydantic tiktoken openai InstructorEmbedding PyMuPDF"
|
||||||
|
msg_info "Installing common Python packages for Rekoni system-wide using uv: $COMMON_REKONI_DEPS"
|
||||||
|
if $STD /usr/local/bin/uv pip install -v --system $COMMON_REKONI_DEPS; then
|
||||||
|
msg_ok "Installed common Python packages system-wide for Rekoni."
|
||||||
|
else
|
||||||
|
msg_error "Failed to install common Python packages system-wide for Rekoni. Rekoni might not work."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Downloading NLTK and Spacy models for Rekoni (using $REKONI_PYTHON_EXEC)"
|
||||||
|
NLTK_MODELS="punkt stopwords wordnet omw-1.4" # Open Multilingual Wordnet
|
||||||
|
SPACY_MODEL="en_core_web_sm" # Small English model
|
||||||
|
|
||||||
|
# Ensure NLTK_DATA directory exists and is writable if needed, or use a user-writable path
|
||||||
|
# For system-wide, /usr/share/nltk_data is common. For venv, it might be within the venv.
|
||||||
|
# The -d flag for nltk.downloader specifies the download directory.
|
||||||
|
NLTK_DATA_DIR="/usr/share/nltk_data"
|
||||||
|
$STD mkdir -p "$NLTK_DATA_DIR"
|
||||||
|
# Grant write permission temporarily if needed, or run as root.
|
||||||
|
# For simplicity in script, assuming root or sudo for system-wide.
|
||||||
|
if ! $STD $REKONI_PYTHON_EXEC -m nltk.downloader -d "$NLTK_DATA_DIR" $NLTK_MODELS; then
|
||||||
|
msg_warn "NLTK model download failed for some components ($NLTK_MODELS) using $REKONI_PYTHON_EXEC. This might affect Rekoni functionality."
|
||||||
|
fi
|
||||||
|
if ! $STD $REKONI_PYTHON_EXEC -m spacy download $SPACY_MODEL; then
|
||||||
|
msg_warn "Spacy model $SPACY_MODEL download failed using $REKONI_PYTHON_EXEC. This might affect Rekoni functionality."
|
||||||
|
fi
|
||||||
|
msg_ok "Python setup for Rekoni completed. Rekoni will run using: $REKONI_PYTHON_EXEC"
|
||||||
|
|
||||||
msg_info "Removing Docker"
|
msg_info "Removing Docker"
|
||||||
# Stop and remove Docker since we only needed it for extraction
|
|
||||||
$STD systemctl stop docker
|
$STD systemctl stop docker
|
||||||
$STD apt-get remove -y docker-ce docker-ce-cli containerd.io
|
$STD apt-get remove -y docker-ce docker-ce-cli containerd.io
|
||||||
$STD rm -rf /var/lib/docker
|
$STD apt-get purge -y docker-ce docker-ce-cli containerd.io --allow-remove-essential
|
||||||
|
$STD rm -rf /var/lib/docker /var/lib/containerd
|
||||||
$STD rm -f /etc/apt/sources.list.d/docker.list /etc/apt/keyrings/docker.gpg
|
$STD rm -f /etc/apt/sources.list.d/docker.list /etc/apt/keyrings/docker.gpg
|
||||||
msg_ok "Removed Docker"
|
msg_ok "Removed Docker"
|
||||||
|
|
||||||
msg_info "Configuring nginx"
|
msg_info "Configuring Nginx as reverse proxy"
|
||||||
# Remove default nginx site
|
|
||||||
$STD rm -f /etc/nginx/sites-enabled/default
|
$STD rm -f /etc/nginx/sites-enabled/default
|
||||||
|
|
||||||
# Create nginx configuration for native Huly
|
|
||||||
cat <<EOF >/etc/nginx/sites-available/huly.conf
|
cat <<EOF >/etc/nginx/sites-available/huly.conf
|
||||||
server {
|
server {
|
||||||
listen 80 default_server;
|
listen 80 default_server;
|
||||||
listen [::]:80 default_server;
|
listen [::]:80 default_server;
|
||||||
server_name _;
|
server_name _; # Replace with your domain if you have one
|
||||||
|
|
||||||
# Frontend
|
client_max_body_size 100M; # For file uploads via transactor
|
||||||
|
|
||||||
|
# Source the config file to get port variables for nginx
|
||||||
|
# Note: This is a bash-ism. Nginx doesn't directly execute this.
|
||||||
|
# Ports must be hardcoded or managed by a script that generates this nginx config.
|
||||||
|
# For simplicity, using fixed ports here, matching native.conf defaults.
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://127.0.0.1:3000;
|
proxy_pass http://127.0.0.1:3000; # Huly Frontend (FRONT_PORT)
|
||||||
proxy_set_header Host \$host;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header X-Real-IP \$remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
|
||||||
proxy_set_header Upgrade \$http_upgrade;
|
proxy_set_header Upgrade \$http_upgrade;
|
||||||
proxy_set_header Connection "upgrade";
|
proxy_set_header Connection "upgrade"; # For WebSockets if front uses them directly
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
proxy_read_timeout 300s; # Increase timeout for potentially long operations
|
||||||
|
proxy_send_timeout 300s;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Account service
|
|
||||||
location /account/ {
|
location /account/ {
|
||||||
proxy_pass http://127.0.0.1:3001/;
|
proxy_pass http://127.0.0.1:3001/; # Huly Account (ACCOUNT_PORT)
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Transactor handles general API and WebSocket for collaboration
|
||||||
|
location /transactor/ {
|
||||||
|
proxy_pass http://127.0.0.1:3002/; # Huly Transactor (TRANSACTOR_PORT)
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade; # Essential for WebSocket
|
||||||
|
proxy_set_header Connection "upgrade"; # Essential for WebSocket
|
||||||
proxy_set_header Host \$host;
|
proxy_set_header Host \$host;
|
||||||
proxy_set_header X-Real-IP \$remote_addr;
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
# MinIO (file storage)
|
# Specific path for uploads if front uses /upload directly to transactor
|
||||||
location /files/ {
|
# Ensure this matches how the frontend makes upload requests.
|
||||||
proxy_pass http://127.0.0.1:9000/;
|
# If uploads go via /transactor/upload, this specific block might not be needed.
|
||||||
|
location /upload {
|
||||||
|
proxy_pass http://127.0.0.1:3002/upload; # Huly Transactor Upload (TRANSACTOR_PORT)
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
client_max_body_size 100M; # Ensure this is set for uploads
|
||||||
|
}
|
||||||
|
|
||||||
|
location /collaborator/ {
|
||||||
|
proxy_pass http://127.0.0.1:3078/; # Huly Collaborator (COLLABORATOR_PORT)
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade \$http_upgrade; # Essential for WebSocket
|
||||||
|
proxy_set_header Connection "upgrade"; # Essential for WebSocket
|
||||||
proxy_set_header Host \$host;
|
proxy_set_header Host \$host;
|
||||||
proxy_set_header X-Real-IP \$remote_addr;
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /rekoni/ {
|
||||||
|
proxy_pass http://127.0.0.1:4004/; # Huly Rekoni (REKONI_PORT)
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# MinIO Console access (if needed through reverse proxy, otherwise direct access on :9001)
|
||||||
|
# location /minio-console/ {
|
||||||
|
# proxy_pass http://127.0.0.1:9001/;
|
||||||
|
# proxy_set_header Host \$host;
|
||||||
|
# }
|
||||||
|
|
||||||
|
# MinIO API/S3 access (if needed through reverse proxy)
|
||||||
|
# Usually, services access MinIO directly on localhost:9000
|
||||||
|
# location /s3/ { # Example path, adjust as needed
|
||||||
|
# proxy_pass http://127.0.0.1:9000/;
|
||||||
|
# proxy_set_header Host \$host; # Important for MinIO to work correctly
|
||||||
|
# }
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
$STD ln -sf /etc/nginx/sites-available/huly.conf /etc/nginx/sites-enabled/huly.conf
|
$STD ln -sf /etc/nginx/sites-available/huly.conf /etc/nginx/sites-enabled/huly.conf
|
||||||
|
|
||||||
# Test and reload nginx
|
|
||||||
if nginx -t >/dev/null 2>&1; then
|
if nginx -t >/dev/null 2>&1; then
|
||||||
$STD nginx -s reload
|
$STD systemctl reload nginx
|
||||||
|
msg_ok "Nginx configured and reloaded."
|
||||||
else
|
else
|
||||||
msg_error "nginx configuration test failed"
|
msg_error "Nginx configuration test failed. Please check /etc/nginx/sites-available/huly.conf and nginx logs (journalctl -u nginx)."
|
||||||
|
# Optionally, print nginx -t output for debugging
|
||||||
|
nginx -t
|
||||||
fi
|
fi
|
||||||
msg_ok "nginx configured"
|
|
||||||
|
|
||||||
msg_info "Creating systemd services for Huly components"
|
# Source the config file to get variables for systemd units
|
||||||
|
# This ensures systemd units use the values from native.conf
|
||||||
|
if [ -f /opt/huly-selfhost/native.conf ]; then
|
||||||
|
source /opt/huly-selfhost/native.conf
|
||||||
|
else
|
||||||
|
msg_error "Huly configuration file /opt/huly-selfhost/native.conf not found. Cannot create systemd services correctly."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg_info "Creating systemd services for Huly components and MinIO"
|
||||||
|
|
||||||
# MinIO service
|
# MinIO service
|
||||||
cat <<EOF >/etc/systemd/system/minio.service
|
cat <<EOF >/etc/systemd/system/minio.service
|
||||||
@ -211,45 +389,65 @@ AssertFileIsExecutable=/usr/local/bin/minio
|
|||||||
WorkingDirectory=/opt/minio
|
WorkingDirectory=/opt/minio
|
||||||
User=minio
|
User=minio
|
||||||
Group=minio
|
Group=minio
|
||||||
EnvironmentFile=/etc/minio/minio.conf
|
EnvironmentFile=/etc/minio/minio.conf # Contains MINIO_ROOT_USER, MINIO_ROOT_PASSWORD, MINIO_VOLUMES, MINIO_OPTS
|
||||||
ExecStartPre=/bin/bash -c "if [ -z \"\${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/minio/minio.conf\"; exit 1; fi"
|
ExecStartPre=/bin/bash -c "if [ -z \\"\${MINIO_VOLUMES}\\" ]; then echo 'Variable MINIO_VOLUMES not set in /etc/minio/minio.conf'; exit 1; fi"
|
||||||
ExecStart=/usr/local/bin/minio server \$MINIO_OPTS \$MINIO_VOLUMES
|
ExecStart=/usr/local/bin/minio server \$MINIO_OPTS \$MINIO_VOLUMES
|
||||||
Restart=always
|
Restart=always
|
||||||
LimitNOFILE=65536
|
LimitNOFILE=1048576
|
||||||
TasksMax=infinity
|
TasksMax=infinity
|
||||||
TimeoutStopSec=infinity
|
TimeoutStopSec=infinity # Or a reasonable timeout
|
||||||
SendSIGKILL=no
|
SendSIGKILL=no
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Huly User for services (optional, but good practice)
|
||||||
|
# useradd -r -s /bin/false hulyuser 2>/dev/null || true
|
||||||
|
|
||||||
# Frontend service
|
# Frontend service
|
||||||
|
# Check if the entrypoint is bundle.js or server.js or main.js - adjust ExecStart
|
||||||
|
# Common for Node.js apps: dist/bundle.js, dist/main.js, server.js, app.js
|
||||||
|
# Assuming /opt/huly/front/dist/bundle.js from previous observations
|
||||||
|
FRONT_EXEC_PATH="/opt/huly/front/dist/bundle.js" # Default, adjust if different
|
||||||
|
if [ ! -f "$FRONT_EXEC_PATH" ] && [ -f "/opt/huly/front/bundle.js" ]; then FRONT_EXEC_PATH="/opt/huly/front/bundle.js"; fi
|
||||||
|
if [ ! -f "$FRONT_EXEC_PATH" ] && [ -f "/opt/huly/front/main.js" ]; then FRONT_EXEC_PATH="/opt/huly/front/main.js"; fi
|
||||||
|
if [ ! -f "$FRONT_EXEC_PATH" ] && [ -f "/opt/huly/front/server.js" ]; then FRONT_EXEC_PATH="/opt/huly/front/server.js"; fi
|
||||||
|
# Add more checks if necessary, or make it configurable
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/huly-front.service
|
cat <<EOF >/etc/systemd/system/huly-front.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Huly Frontend Service
|
Description=Huly Frontend Service
|
||||||
After=network.target
|
After=network.target nginx.service huly-account.service huly-transactor.service huly-rekoni.service huly-collaborator.service
|
||||||
|
Wants=nginx.service huly-account.service huly-transactor.service huly-rekoni.service huly-collaborator.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=/opt/huly/front
|
WorkingDirectory=/opt/huly/front
|
||||||
ExecStart=/usr/bin/node dist/bundle.js
|
ExecStart=/usr/bin/node $FRONT_EXEC_PATH
|
||||||
Restart=always
|
Restart=always
|
||||||
User=root
|
User=root # Consider 'hulyuser' or 'www-data' if created and permissions allow
|
||||||
Environment=PORT=3000
|
EnvironmentFile=/opt/huly-selfhost/native.conf # Sources all needed env vars
|
||||||
Environment=NODE_ENV=production
|
# Explicitly set PORT if not in native.conf or to override
|
||||||
Environment=ACCOUNTS_URL=http://localhost:3001
|
Environment="PORT=\${FRONT_PORT:-3000}"
|
||||||
Environment=UPLOAD_URL=http://localhost:8086/files
|
Environment="NODE_ENV=production"
|
||||||
Environment=ELASTIC_URL=http://localhost:9200
|
# URLs should be sourced from native.conf or constructed if services are on different hosts
|
||||||
Environment=GMAIL_URL=http://localhost:8087
|
Environment="ACCOUNTS_URL=http://localhost:\${ACCOUNT_PORT:-3001}"
|
||||||
Environment=CALENDAR_URL=http://localhost:8095
|
Environment="UPLOAD_URL=http://localhost:\${TRANSACTOR_PORT:-3002}/upload" # Ensure this path is correct
|
||||||
Environment=REKONI_URL=http://localhost:4004
|
Environment="REKONI_URL=http://localhost:\${REKONI_PORT:-4004}"
|
||||||
|
Environment="COLLABORATOR_URL=ws://localhost:\${COLLABORATOR_PORT:-3078}" # Note: ws:// for collaborator
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Account service
|
# Account service
|
||||||
|
ACCOUNT_EXEC_PATH="/opt/huly/account/bundle.js" # Default
|
||||||
|
if [ ! -f "$ACCOUNT_EXEC_PATH" ] && [ -f "/opt/huly/account/main.js" ]; then ACCOUNT_EXEC_PATH="/opt/huly/account/main.js"; fi
|
||||||
|
# ... add other checks for account executable
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/huly-account.service
|
cat <<EOF >/etc/systemd/system/huly-account.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Huly Account Service
|
Description=Huly Account Service
|
||||||
@ -259,43 +457,54 @@ Requires=mongod.service
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=/opt/huly/account
|
WorkingDirectory=/opt/huly/account
|
||||||
ExecStart=/usr/bin/node bundle.js
|
ExecStart=/usr/bin/node $ACCOUNT_EXEC_PATH
|
||||||
Restart=always
|
Restart=always
|
||||||
User=root
|
User=root # Consider 'hulyuser'
|
||||||
Environment=PORT=3001
|
EnvironmentFile=/opt/huly-selfhost/native.conf
|
||||||
Environment=MONGO_URL=mongodb://huly:hulypassword123@localhost:27017/huly
|
Environment="PORT=\${ACCOUNT_PORT:-3001}"
|
||||||
Environment=TRANSACTOR_URL=ws://localhost:3002
|
Environment="TRANSACTOR_URL=ws://localhost:\${TRANSACTOR_PORT:-3002}" # Ensure ws or wss
|
||||||
Environment=SECRET=secret
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Transactor service
|
# Transactor service
|
||||||
|
TRANSACTOR_EXEC_PATH="/opt/huly/transactor/bundle.js" # Default
|
||||||
|
if [ ! -f "$TRANSACTOR_EXEC_PATH" ] && [ -f "/opt/huly/transactor/main.js" ]; then TRANSACTOR_EXEC_PATH="/opt/huly/transactor/main.js"; fi
|
||||||
|
# ... add other checks for transactor executable
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/huly-transactor.service
|
cat <<EOF >/etc/systemd/system/huly-transactor.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Huly Transactor Service
|
Description=Huly Transactor Service
|
||||||
After=network.target mongod.service minio.service
|
After=network.target mongod.service minio.service huly-account.service
|
||||||
Requires=mongod.service minio.service
|
Requires=mongod.service minio.service huly-account.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=/opt/huly/transactor
|
WorkingDirectory=/opt/huly/transactor
|
||||||
ExecStart=/usr/bin/node bundle.js
|
ExecStart=/usr/bin/node $TRANSACTOR_EXEC_PATH
|
||||||
Restart=always
|
Restart=always
|
||||||
User=root
|
User=root # Consider 'hulyuser'
|
||||||
Environment=PORT=3002
|
EnvironmentFile=/opt/huly-selfhost/native.conf
|
||||||
Environment=MONGO_URL=mongodb://huly:hulypassword123@localhost:27017/huly
|
Environment="PORT=\${TRANSACTOR_PORT:-3002}"
|
||||||
Environment=STORAGE_CONFIG=minio|minio?accessKey=minioadmin&secretKey=minioadmin
|
# STORAGE_CONFIG needs careful construction based on native.conf values
|
||||||
Environment=SECRET=secret
|
Environment="STORAGE_CONFIG=minio|minio?accessKey=\${MINIO_ACCESS_KEY}&secretKey=\${MINIO_SECRET_KEY}&endpoint=\${MINIO_ENDPOINT}&secure=false" # Assuming http for minio
|
||||||
Environment=ACCOUNTS_URL=http://localhost:3001
|
Environment="ACCOUNTS_URL=http://localhost:\${ACCOUNT_PORT:-3001}"
|
||||||
Environment=REKONI_URL=http://localhost:4004
|
Environment="REKONI_URL=http://localhost:\${REKONI_PORT:-4004}"
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Collaborator service
|
# Collaborator service
|
||||||
|
COLLABORATOR_EXEC_PATH="/opt/huly/collaborator/dist/bundle.js" # Default
|
||||||
|
if [ ! -f "$COLLABORATOR_EXEC_PATH" ] && [ -f "/opt/huly/collaborator/bundle.js" ]; then COLLABORATOR_EXEC_PATH="/opt/huly/collaborator/bundle.js"; fi
|
||||||
|
# ... add other checks for collaborator executable
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/huly-collaborator.service
|
cat <<EOF >/etc/systemd/system/huly-collaborator.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Huly Collaborator Service
|
Description=Huly Collaborator Service
|
||||||
@ -305,58 +514,89 @@ Requires=mongod.service
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=/opt/huly/collaborator
|
WorkingDirectory=/opt/huly/collaborator
|
||||||
ExecStart=/usr/bin/node dist/bundle.js
|
ExecStart=/usr/bin/node $COLLABORATOR_EXEC_PATH
|
||||||
Restart=always
|
Restart=always
|
||||||
User=root
|
User=root # Consider 'hulyuser'
|
||||||
Environment=PORT=3078
|
EnvironmentFile=/opt/huly-selfhost/native.conf
|
||||||
Environment=MONGO_URL=mongodb://huly:hulypassword123@localhost:27017/huly
|
Environment="PORT=\${COLLABORATOR_PORT:-3078}"
|
||||||
Environment=SECRET=secret
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Rekoni service (file processing)
|
# Rekoni service
|
||||||
|
# Rekoni is Python, ExecStart uses the determined $REKONI_PYTHON_EXEC
|
||||||
|
# Ensure main.py (or equivalent) is the entrypoint in /opt/huly/rekoni/
|
||||||
|
REKONI_ENTRYPOINT="main.py" # Default, ensure this file exists in /opt/huly/rekoni
|
||||||
|
if [ ! -f "/opt/huly/rekoni/$REKONI_ENTRYPOINT" ]; then
|
||||||
|
msg_warn "Rekoni entrypoint $REKONI_ENTRYPOINT not found in /opt/huly/rekoni/. Service might fail."
|
||||||
|
# Potentially look for app.py or other common Python entrypoints if main.py is missing
|
||||||
|
fi
|
||||||
|
|
||||||
cat <<EOF >/etc/systemd/system/huly-rekoni.service
|
cat <<EOF >/etc/systemd/system/huly-rekoni.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Huly Rekoni Service
|
Description=Huly Rekoni Service (File Processing)
|
||||||
After=network.target
|
After=network.target mongod.service minio.service
|
||||||
|
Requires=mongod.service minio.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=/opt/huly/rekoni
|
WorkingDirectory=/opt/huly/rekoni
|
||||||
ExecStart=/usr/bin/node bundle.js
|
ExecStart=$REKONI_PYTHON_EXEC $REKONI_ENTRYPOINT
|
||||||
Restart=always
|
Restart=always
|
||||||
User=root
|
User=root # Consider 'hulyuser'
|
||||||
Environment=PORT=4004
|
EnvironmentFile=/opt/huly-selfhost/native.conf
|
||||||
Environment=SECRET=secret
|
Environment="PORT=\${REKONI_PORT:-4004}"
|
||||||
|
Environment="NLTK_DATA=${NLTK_DATA_DIR}" # Pass NLTK data path
|
||||||
|
# Add other Rekoni specific ENV VARS if any, e.g. OPENAI_API_KEY if used and not in native.conf
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Enable and start all services
|
$STD systemctl daemon-reload
|
||||||
systemctl daemon-reload
|
# Enable services (start them on boot)
|
||||||
systemctl enable --now minio huly-front huly-account huly-transactor huly-collaborator huly-rekoni
|
$STD systemctl enable minio huly-front huly-account huly-transactor huly-collaborator huly-rekoni mongod nginx
|
||||||
msg_ok "Created and started Huly services"
|
# Start services now
|
||||||
|
$STD systemctl start minio mongod # Start dependencies first
|
||||||
|
# Brief pause to allow DB/MinIO to initialize before dependent services start
|
||||||
|
sleep 5
|
||||||
|
$STD systemctl start nginx huly-account # Account needs Mongo
|
||||||
|
sleep 2
|
||||||
|
$STD systemctl start huly-transactor huly-rekoni # These need Account, Mongo, Minio
|
||||||
|
sleep 2
|
||||||
|
$STD systemctl start huly-collaborator # Needs Mongo
|
||||||
|
sleep 2
|
||||||
|
$STD systemctl start huly-front # Front needs all backends
|
||||||
|
|
||||||
|
msg_ok "Created, enabled, and started Huly services and dependencies"
|
||||||
|
|
||||||
|
# Create version file to track installations and updates
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - Initial Install of Huly Native" >/opt/huly-selfhost/version.txt
|
||||||
|
|
||||||
motd_ssh
|
motd_ssh
|
||||||
customize
|
customize
|
||||||
|
|
||||||
msg_info "Cleaning up"
|
# Cleanup
|
||||||
|
msg_info "Cleaning up apt cache and unused packages"
|
||||||
$STD apt-get -y autoremove
|
$STD apt-get -y autoremove
|
||||||
$STD apt-get -y autoclean
|
$STD apt-get -y autoclean
|
||||||
msg_ok "Cleaned"
|
msg_ok "Cleaned up"
|
||||||
|
|
||||||
echo -e "${INFO}${YW} Huly native installation completed successfully!${CL}"
|
echo -e "${INFO}${YW} Huly native installation completed successfully!${CL}"
|
||||||
echo -e "${INFO}${YW} Access URL: http://$SERVER_IP${CL}"
|
echo -e "${INFO}${YW} Access URL: http://$SERVER_IP (or your configured domain)${CL}"
|
||||||
echo -e "${INFO}${YW} Services may take a few minutes to fully start.${CL}"
|
echo -e "${INFO}${YW} Services may take a few moments to fully initialize.${CL}"
|
||||||
echo -e ""
|
echo -e ""
|
||||||
echo -e "${INFO}${YW} Service Status Commands:${CL}"
|
echo -e "${INFO}${YW} Service Status Commands:${CL}"
|
||||||
echo -e "${INFO}${YW} • Check all services: systemctl status minio huly-front huly-account huly-transactor${CL}"
|
echo -e "${INFO}${YW} • Check all Huly services: systemctl status 'huly-*' minio mongod nginx ${CL}"
|
||||||
echo -e "${INFO}${YW} • View frontend logs: journalctl -f -u huly-front${CL}"
|
echo -e "${INFO}${YW} • Example: systemctl status huly-front ${CL}"
|
||||||
echo -e "${INFO}${YW} • View account logs: journalctl -f -u huly-account${CL}"
|
echo -e "${INFO}${YW} • View logs: journalctl -u <service_name> -f (e.g., journalctl -u huly-front -f)${CL}"
|
||||||
echo -e "${INFO}${YW} • MinIO Console: http://$SERVER_IP:9001 (minioadmin/minioadmin)${CL}"
|
echo -e "${INFO}${YW} • MinIO Console: http://$SERVER_IP:9001 (User: ${MINIO_ACCESS_KEY}, Pass: ${MINIO_SECRET_KEY})${CL}"
|
||||||
echo -e ""
|
echo -e ""
|
||||||
echo -e "${INFO}${YW} Configuration saved to: /opt/huly-selfhost/native.conf${CL}"
|
echo -e "${INFO}${YW} IMPORTANT: Review credentials in ~/huly.creds and store them securely.${CL}"
|
||||||
echo -e "${INFO}${YW} VAPID keys included in configuration for push notifications${CL}"
|
echo -e "${INFO}${YW} Configuration is in: /opt/huly-selfhost/native.conf${CL}"
|
||||||
|
echo -e "${INFO}${YW} Rekoni Python executable: $REKONI_PYTHON_EXEC ${CL}"
|
||||||
|
|||||||
Reference in New Issue
Block a user