install_hestiacp_admin.sh is a comprehensive PUQcloud installation script for HestiaCP that operates with administrative privileges and provides full system control. The script automates the entire installation and configuration process of PUQcloud with support for modern technologies and security best practices.
- ✅ Root privileges operation - full access to system functions
- ✅ HestiaCP CLI integration - use of built-in management commands
- ✅ Automatic user and domain selection - interactive menus
- ✅ System services management - Redis, Supervisor, PHP-FPM
- 🔴 Automatic Redis installation and configuration with password
- 🟢 Node.js installation via official repository
- 🔵 Laravel Horizon for queue management
- ⚙️ Supervisor for process monitoring
- 🎨 Automatic frontend assets compilation
- 🔒 pcntl functions configuration for proper Horizon operation
- 🔄 Regular update - standard update process
- 💥 Hard update - with full migration rollback
- ⏸️ Safe update - with process suspension
- 🛡️ Security verification after update
See diagram above
# Interactive mode
sudo bash install_hestiacp_admin.sh
# With parameters
sudo bash install_hestiacp_admin.sh [user] [domain] [admin_email] [admin_password] [admin_name]
# Example
sudo bash install_hestiacp_admin.sh myuser mydomain.com admin@mydomain.com mypassword "Admin Name"# REQUIRED: root privileges
sudo su
# Check HestiaCP
ls /usr/local/hestia
# Check CLI commands
v-list-users# Check if we're running as root or have admin privileges
check_admin_privileges() {
if [ "$EUID" -ne 0 ]; then
type_text "Error: This script must be run as root or with sudo."
exit 1
fi
if [ ! -d "/usr/local/hestia" ]; then
type_text "Error: HestiaCP not detected."
exit 1
fi
}What happens:
- Check execution as root (
EUID -ne 0) - Check HestiaCP presence (
/usr/local/hestia) - Check HestiaCP CLI commands availability (
v-list-users)
# Configuration file for saving previous values
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/install_config_admin.txt"What happens:
- Load previous values from configuration file
- Save current settings for reuse
- Simplify reinstallation or update process
# Get list of users
USERS_LIST=$(v-list-users plain 2>/dev/null | awk '{print $1}' | grep -v "USER" | grep -v "^$")
# Show selection menu
type_text "Available HestiaCP users:"
for i in "${!USERS_ARRAY[@]}"; do
echo " $((i+1))) ${USERS_ARRAY[$i]}"
doneWhat happens:
- Retrieve list of all HestiaCP users via CLI
- Display interactive selection menu
- Option for manual username input
# Get list of domains for the selected user
DOMAINS_LIST=$(v-list-web-domains "$HESTIA_USER" plain 2>/dev/null | awk '{print $1}')
# Show selection menu with domains
for i in "${!DOMAINS_ARRAY[@]}"; do
echo " $((i+1))) ${DOMAINS_ARRAY[$i]}"
doneWhat happens:
- Retrieve domain list for selected user
- Interactive selection from existing domains
- Option to specify custom domain
# Generate secure Redis password
REDIS_PASSWORD="$(tr -dc 'a-zA-Z0-9!@$%^&*()_+=-' </dev/urandom | head -c 32)"
# Install Redis server if not present
if ! command -v redis-server &> /dev/null; then
apt update && apt install -y redis-server
fi
# Configure Redis with password authentication
echo "requirepass $REDIS_PASSWORD" >> "$REDIS_CONFIG"
echo "bind 127.0.0.1 ::1" >> "$REDIS_CONFIG"
echo "protected-mode no" >> "$REDIS_CONFIG"What happens:
- Generate secure Redis password (32 characters)
- Install Redis server via apt
- Configure password authentication
- Restrict access to localhost only
- Automatic Redis restart with new configuration
- Install PHP Redis extension
# Install Node.js and npm
if ! command -v node &> /dev/null || ! command -v npm &> /dev/null; then
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
apt install -y nodejs
fiWhat happens:
- Check Node.js and npm availability
- Add official NodeSource repository
- Install latest LTS Node.js version
- Verify installation success
# Enable pcntl functions for Laravel Horizon
for php_version in $($HESTIA/bin/v-list-sys-php plain); do
PCNTL_CLI_CONFIG="/etc/php/$php_version/cli/conf.d/99-enable-pcntl.ini"
# Remove pcntl functions from disable_functions
CURRENT_DISABLED=$(php$php_version -i | grep "disable_functions")
NEW_DISABLED=$(echo "$CURRENT_DISABLED" | sed 's/pcntl_[^,]*,\?//g')
echo "disable_functions = $NEW_DISABLED" >> "$PCNTL_CLI_CONFIG"
doneWhat happens:
- Get list of all installed PHP versions
- Create configuration files for CLI and FPM
- Remove pcntl functions from disabled list
- Restart PHP-FPM services
- Required for proper Laravel Horizon operation
# Generate database credentials
DB_NAME_CLEAN="puqcloud_$(tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 8)"
DB_USER_CLEAN="puq_$(tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 8)"
DB_PASS="$(tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 16)"
# Create database via HestiaCP CLI
v-add-database "$HESTIA_USER" "$DB_NAME_CLEAN" "$DB_USER_CLEAN" "$DB_PASS"What happens:
- Generate random secure database and user names
- Create database via HestiaCP CLI
- Automatic user prefix addition
- Fallback to manual creation on failure
# Install Horizon via Composer as target user
sudo -u "$HESTIA_USER" "$COMPOSER_PATH" require laravel/horizon --no-interaction
# Publish Horizon assets
sudo -u "$HESTIA_USER" php artisan horizon:publishWhat happens:
- Install Laravel Horizon via Composer
- Execute commands as target user
- Publish assets for Horizon web interface
- Prepare for Redis queue operations
# Check if user has NVM installation
NVM_DIR="/home/$HESTIA_USER/.nvm"
if [ -d "$NVM_DIR" ]; then
# Use NVM Node.js
NPM_PATH="$NVM_DIR/versions/node/$NODE_VERSION/bin/npm"
else
# Use global Node.js
NPM_PATH=$(which npm)
fi
# Install npm dependencies and compile
sudo -u "$HESTIA_USER" "$NPM_PATH" install
sudo -u "$HESTIA_USER" "$NPM_PATH" run prodWhat happens:
- Determine npm path (NVM or global installation)
- Clear cache and old node_modules
- Install dependencies as user
- Compile production assets
- Verify mix-manifest.json creation
# Get server timezone automatically
SERVER_TIMEZONE=$(get_server_timezone)
# Set basic application settings for production
sed -i "s/APP_ENV=.*/APP_ENV=production/" .env
sed -i "s/APP_DEBUG=.*/APP_DEBUG=false/" .env
sed -i "s|APP_TIMEZONE=.*|APP_TIMEZONE=${SERVER_TIMEZONE}|" .env
# Redis configuration with password
sed -i "s/REDIS_CLIENT=.*/REDIS_CLIENT=phpredis/" .env
echo "REDIS_PASSWORD=${REDIS_PASSWORD}" >> .envWhat happens:
- Automatic server timezone detection
- Configure production environment (DEBUG=false)
- Configure Redis with password
- Set queues and cache to Redis
- Set TEMPLATE_CLIENT=puqcloud (critically important!)
# Create Horizon configuration for Supervisor
cat <<EOL > /etc/supervisor/conf.d/horizon-${HESTIA_USER}-${DOMAIN}.conf
[program:horizon-${HESTIA_USER}-${DOMAIN}]
process_name=%(program_name)s
command=php $PROJECT_PATH/artisan horizon
autostart=true
autorestart=true
user=$HESTIA_USER
redirect_stderr=true
stdout_logfile=$PROJECT_PATH/storage/logs/horizon.log
stopwaitsecs=3600
EOL
# Reload and start
supervisorctl reread
supervisorctl update
supervisorctl start horizon-${HESTIA_USER}-${DOMAIN}What happens:
- Create Supervisor configuration for Horizon
- Unique program name for each user/domain
- Automatic start and restart
- Logging to storage/logs/horizon.log
- Proper process termination (stopwaitsecs=3600)
# Check for existing Laravel scheduler cron job
find_laravel_cron_job() {
v-list-cron-jobs "$HESTIA_USER" plain | grep "artisan schedule:run" | awk '{print $1}'
}
# Create new cron job via HestiaCP CLI
CRON_COMMAND="cd $PROJECT_PATH && php artisan schedule:run >> /dev/null 2>&1"
v-add-cron-job "$HESTIA_USER" "*" "*" "*" "*" "*" "$CRON_COMMAND"What happens:
- Check existing cron jobs via HestiaCP CLI
- Update existing job or create new one
- Use HestiaCP CLI for cron management
- Fallback to standard crontab on failure
- Configure Laravel Scheduler (every minute)
# Suspend Laravel scheduler before update
suspend_laravel_cron_job() {
CRON_JOB_ID=$(find_laravel_cron_job true)
v-suspend-cron-job "$HESTIA_USER" "$CRON_JOB_ID" no
}
# Hard update option with migration rollback
if [[ "$hard_update" == "Yes" ]]; then
while [ $ROLLBACK_COUNT -lt $MAX_ROLLBACKS ]; do
sudo -u "$HESTIA_USER" php artisan migrate:rollback --force --step=1
ROLLBACK_COUNT=$((ROLLBACK_COUNT + 1))
done
fiWhat happens:
- Suspend cron jobs before update
- Stop Horizon processes
- Optional hard update with full migration rollback
- Safe rollback counter (maximum 50)
- Update repository and dependencies
- Resume all processes after update
# Check production security settings
verify_production_security() {
DEBUG_SETTING=$(grep "^APP_DEBUG=" .env | cut -d'=' -f2)
if [[ "$DEBUG_SETTING" == "false" ]]; then
type_text "✓ APP_DEBUG is safely set to false"
fi
ENV_SETTING=$(grep "^APP_ENV=" .env | cut -d'=' -f2)
if [[ "$ENV_SETTING" == "production" ]]; then
type_text "✓ APP_ENV is correctly set to production"
fi
}What happens:
- Check APP_DEBUG=false
- Check APP_ENV=production
- Check LOG_LEVEL=error
- Check Redis password presence
- Warnings about insecure settings
# All commands executed as target user
sudo -u "$HESTIA_USER" command
# Proper user path configuration
PATH="/home/$HESTIA_USER/.local/bin:$PATH"
# File ownership configuration
chown -R "$HESTIA_USER:www-data" "$PROJECT_PATH"# Example of safe installation with fallback
if v-add-database "$HESTIA_USER" "$DB_NAME_CLEAN" "$DB_USER_CLEAN" "$DB_PASS"; then
type_text "✓ Database created successfully!"
else
type_text "❌ Failed to create database via HestiaCP CLI."
type_text "Please create database manually..."
read -p "Press Enter after creating the database..."
fi# Server timezone detection
get_server_timezone() {
if command -v timedatectl &> /dev/null; then
timezone=$(timedatectl show --property=Timezone --value)
elif [ -f /etc/timezone ]; then
timezone=$(cat /etc/timezone)
else
timezone="UTC"
fi
echo "$timezone"
}- Must run with sudo - script requires root privileges
- Redis password protection - automatically generates secure password
- Production settings - APP_DEBUG=false, LOG_LEVEL=error
- File permissions - proper file ownership configuration
- HestiaCP only - script doesn't work without HestiaCP CLI
- Internet required - for downloading dependencies and repository
- Linux only - uses systemctl, apt and other Linux tools
- Test on dev environment before production
- Make backups before updates
- Check logs after installation
- Monitor Horizon via web interface
The install_hestiacp_admin.sh installation script provides a powerful and secure way to deploy PUQcloud in HestiaCP environment with modern technologies and best practices. Complete automation of all installation aspects makes the process fast and reliable, while advanced update and monitoring functions ensure easy system maintenance.
# Connect to server
ssh root@your-server.com
# Download script
wget https://raw.githubusercontent.com/your-repo/install_hestiacp_admin.sh
chmod +x install_hestiacp_admin.sh
# Run interactive installation
sudo bash install_hestiacp_admin.sh
# Select user from list:
# Available HestiaCP users:
# 1) user1
# 2) user2
# 3) testuser
# Select HestiaCP user (1-3 or 0): 2
# Select domain:
# Available domains for user user2:
# 1) example.com
# 2) test.com
# Select domain (1-2 or 0): 1
# Enter administrator data:
# Enter admin email: admin@example.com
# Enter admin password: [secure password]
# Enter admin name: Administratorsudo bash install_hestiacp_admin.sh user2 example.com admin@example.com "SecurePass123" "Site Administrator"# Regular update
sudo bash install_hestiacp_admin.sh
# Select user and domain
# Select "update"
# Select "No" for hard update
# Hard update (with migration rollback)
sudo bash install_hestiacp_admin.sh
# Select user and domain
# Select "update"
# Select "Yes" for hard update# Redis status
systemctl status redis-server
redis-cli -a "your_redis_password" ping
# Supervisor and Horizon status
supervisorctl status
supervisorctl status horizon-user-domain
# Cron jobs status
v-list-cron-jobs username
crontab -u username -l
# Check Horizon logs
tail -f /home/username/web/domain.com/public_html/storage/logs/horizon.logcd /home/username/web/domain.com/public_html
# Check application status
sudo -u username php artisan about
# Check Horizon status
sudo -u username php artisan horizon:status
# Check queues
sudo -u username php artisan queue:monitor
# Check scheduled tasks
sudo -u username php artisan schedule:list# Check Redis logs
journalctl -u redis-server -n 50
# Check configuration
grep "requirepass" /etc/redis/redis.conf
# Restart with correct configuration
systemctl restart redis-server
# Test connection
redis-cli -a "your_password" ping# Check pcntl functions
php -m | grep pcntl
# Check Supervisor configuration
cat /etc/supervisor/conf.d/horizon-*
# Restart Supervisor
supervisorctl reread
supervisorctl update
supervisorctl restart horizon-user-domain
# Check logs
tail -f /home/user/web/domain.com/public_html/storage/logs/horizon.log# Check Node.js
node --version
npm --version
# Check permissions
ls -la /home/user/web/domain.com/public_html/node_modules/
# Manual compilation
cd /home/user/web/domain.com/public_html
sudo -u user npm install --force
sudo -u user npm run prod
# Check result
ls -la public/css/ public/js/
cat public/mix-manifest.json# Check cron jobs in HestiaCP
v-list-cron-jobs username
# Check cron job status
v-list-cron-job username job_id
# Check cron logs
grep "schedule:run" /var/log/syslog
# Manual scheduler run
cd /home/user/web/domain.com/public_html
sudo -u user php artisan schedule:run# Check MySQL connection
mysql -u database_user -p database_name
# Check .env configuration
grep "DB_" /home/user/web/domain.com/public_html/.env
# Test Laravel connection
cd /home/user/web/domain.com/public_html
sudo -u user php artisan migrate:status- User management - automatic selection from HestiaCP users list
- Domain management - interactive selection from existing domains
- Dependency installation - automatic installation of all required components
- Redis with password - automatic installation and secure configuration
- Node.js - installation via official NodeSource repository
- Laravel Horizon - complete queue management setup
- Supervisor - automatic process monitoring configuration
- pcntl functions - automatic enablement for proper Horizon operation
- Production settings - automatic secure environment configuration
- HestiaCP CLI integration - use of built-in management commands
- Hard update support - ability to fully rollback migrations
- Extended security verification - control of critical settings
- Complete assets compilation - modern frontend with optimization
# In script change variable
REPO_URL="https://github.com/your-custom/repo.git"# In install_additional_php_extensions function add
REQUIRED_EXTENSIONS=(
# ... existing extensions ...
"php$PHP_VERSION-imagick"
"php$PHP_VERSION-gd"
"php$PHP_VERSION-intl"
)# Add function for your service
install_your_service() {
type_text "Installing your custom service..."
apt install -y your-service
systemctl enable your-service
systemctl start your-service
}
# Call in main process
install_your_service# User management
v-list-users
v-add-user username password email
# Domain management
v-list-web-domains username
v-add-web-domain username domain.com
# Database management
v-list-databases username
v-add-database username dbname dbuser dbpass
# Cron job management
v-list-cron-jobs username
v-add-cron-job username min hour day month wday command
v-suspend-cron-job username job_id
v-unsuspend-cron-job username job_id# HestiaCP configuration
/usr/local/hestia/conf/hestia.conf
# Redis configuration
/etc/redis/redis.conf
# Supervisor configuration
/etc/supervisor/conf.d/
# PHP configuration
/etc/php/*/cli/conf.d/
/etc/php/*/fpm/conf.d/# User domain
/home/username/web/domain.com/public_html/
# HestiaCP logs
/home/username/web/domain.com/logs/
# Laravel logs
/home/username/web/domain.com/public_html/storage/logs/
# Backups
/home/username/web/domain.com/private/When encountering issues:
- Check logs of all services
- Ensure file permissions are correct
- Check status of all services (Redis, Supervisor, PHP-FPM)
- Check .env file configuration
- Refer to Laravel and HestiaCP documentation
For help, create an issue with detailed problem description and include:
- Script version
- HestiaCP version
- PHP version
- Error logs
- Output of
php artisan aboutcommand