Created
June 21, 2025 07:06
-
-
Save afiqiqmal/ea72c0c727ba5bf0cf3881dcd4e5a40b to your computer and use it in GitHub Desktop.
Initial setup for ubuntu + Laravel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Server Provisioning Script | |
# Edit these variables before running the script | |
################ | |
### CONFIGURATION VARIABLES ### | |
################ | |
USER="your_username" # Replace with desired username | |
USER_PASSWORD="your_secure_password" # Replace with desired user password | |
PROJECT_NAME="your_project" # Replace with project name | |
PROJECT_GIT_URL="https://github.com/user/repo.git" # Replace with your git repository URL | |
OCTANE_PORT="2706" # Port for Laravel Octane | |
OCTANE_WORKERS="2" # Number of Octane workers | |
OCTANE_TASK_WORKERS="2" # Number of Octane task workers | |
OCTANE_MAX_REQUESTS="300" # Max requests per worker | |
################ | |
### SCRIPT START ### | |
################ | |
set -e # Exit on any error | |
echo "================================================" | |
echo "Starting Server Provisioning..." | |
echo "User: $USER" | |
echo "Project: $PROJECT_NAME" | |
echo "================================================" | |
################ | |
### INITIAL SETUP ### | |
################ | |
echo "Step 1: Updating system packages..." | |
sudo apt update | |
echo "Step 2: Adding new user: $USER" | |
if ! id "$USER" &>/dev/null; then | |
sudo adduser --disabled-password --gecos "" $USER | |
echo "$USER:$USER_PASSWORD" | sudo chpasswd | |
sudo usermod -aG sudo $USER | |
echo "User $USER created successfully with password" | |
else | |
echo "User $USER already exists, updating password..." | |
echo "$USER:$USER_PASSWORD" | sudo chpasswd | |
echo "Password updated for user $USER" | |
fi | |
echo "Step 3: Setting up SSH access for $USER" | |
sudo mkdir -p /home/$USER/.ssh | |
sudo cp ~/.ssh/authorized_keys /home/$USER/.ssh/ 2>/dev/null || echo "No SSH keys to copy" | |
sudo chown -R $USER:$USER /home/$USER/.ssh | |
sudo chmod 700 /home/$USER/.ssh | |
sudo chmod 600 /home/$USER/.ssh/authorized_keys 2>/dev/null || true | |
echo "Step 4: Configuring UFW firewall..." | |
sudo ufw --force enable | |
sudo ufw allow OpenSSH | |
sudo ufw allow 'Nginx Full' | |
echo "Step 5: Removing Apache if installed..." | |
sudo systemctl stop apache2 2>/dev/null || true | |
sudo apt-get purge -y apache2 apache2-utils apache2-bin apache2-common 2>/dev/null || true | |
sudo apt-get autoremove -y | |
echo "Step 6: Installing system dependencies..." | |
sudo apt install -y libcurl4-openssl-dev acl unzip | |
echo "Step 7: Installing Nginx..." | |
sudo apt install -y nginx nginx-extras | |
sudo systemctl enable nginx | |
sudo systemctl start nginx | |
echo "Step 8: Installing PHP and extensions..." | |
sudo apt install -y php php-fpm php-cli php-gd php-dom php-xml php-zip php-redis php-bcmath php-mbstring php-intl php-opcache php-mysql php-pgsql php-curl php-dev php-pear | |
echo "Step 9: Installing Swoole extension..." | |
sudo pecl install swoole | |
# Create swoole.ini | |
PHP_VERSION=$(php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;") | |
echo "extension=swoole.so" | sudo tee /etc/php/$PHP_VERSION/mods-available/swoole.ini | |
sudo phpenmod swoole | |
echo "Step 10: Installing Composer..." | |
curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php | |
EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)" | |
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', '/tmp/composer-setup.php');")" | |
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then | |
echo "ERROR: Invalid Composer installer checksum" | |
rm /tmp/composer-setup.php | |
exit 1 | |
fi | |
sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer | |
rm /tmp/composer-setup.php | |
echo "Step 11: Installing Node.js via NVM..." | |
# Install NVM for current user | |
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash | |
export NVM_DIR="$HOME/.nvm" | |
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" | |
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" | |
# Install Node.js and Bun | |
nvm install 23 | |
npm install -g bun | |
echo "Step 12: Installing Supervisor..." | |
sudo apt install -y supervisor | |
sudo systemctl enable supervisor | |
sudo systemctl start supervisor | |
################ | |
### PROJECT SETUP ### | |
################ | |
echo "================================================" | |
echo "Setting up project: $PROJECT_NAME" | |
echo "================================================" | |
echo "Step 13: Creating project directory..." | |
sudo mkdir -p /var/www/$PROJECT_NAME/app | |
sudo chown $USER:www-data /var/www/$PROJECT_NAME/app | |
echo "Step 14: Cloning project repository..." | |
cd /var/www/$PROJECT_NAME/app | |
if [ -d ".git" ]; then | |
echo "Git repository already exists, pulling latest changes..." | |
git pull | |
else | |
git clone $PROJECT_GIT_URL . | |
fi | |
echo "Step 15: Installing Composer dependencies..." | |
composer install --no-dev --optimize-autoloader | |
echo "Step 16: Installing Node.js dependencies and building assets..." | |
bun install | |
bun run build | |
echo "Step 17: Setting correct permissions..." | |
sudo chown -R $USER:www-data /var/www/$PROJECT_NAME/app | |
sudo find /var/www/$PROJECT_NAME/app -type d -exec chmod 775 {} \; | |
sudo find /var/www/$PROJECT_NAME/app -type f -exec chmod 664 {} \; | |
sudo chgrp -R www-data storage bootstrap/cache | |
sudo chmod -R ug+rwx storage bootstrap/cache | |
sudo rm -rf storage/logs/daily 2>/dev/null || true | |
sudo setfacl -d -m g::rwx storage/logs | |
echo "Step 18: Setting up cron job for Laravel scheduler..." | |
(sudo crontab -u www-data -l 2>/dev/null; echo "* * * * * php /var/www/$PROJECT_NAME/app/artisan schedule:run >> /dev/null 2>&1") | sudo crontab -u www-data - | |
echo "Step 19: Setting up Supervisor configuration for Octane..." | |
sudo tee /etc/supervisor/conf.d/${PROJECT_NAME}-octane.conf > /dev/null <<EOF | |
[program:${PROJECT_NAME}_octane] | |
process_name=%(program_name)s_%(process_num)02d | |
command=php /var/www/$PROJECT_NAME/app/artisan octane:start --server=swoole --workers=$OCTANE_WORKERS --task-workers=$OCTANE_TASK_WORKERS --port=$OCTANE_PORT --max-requests=$OCTANE_MAX_REQUESTS | |
autostart=true | |
autorestart=true | |
user=www-data | |
group=www-data | |
redirect_stderr=true | |
stdout_logfile=/var/www/$PROJECT_NAME/app/storage/logs/octane.log | |
stopwaitsecs=3600 | |
EOF | |
echo "Step 20: Setting up Supervisor configuration for Horizon..." | |
sudo tee /etc/supervisor/conf.d/${PROJECT_NAME}-horizon.conf > /dev/null <<EOF | |
[program:${PROJECT_NAME}_horizon] | |
process_name=%(program_name)s | |
command=php /var/www/$PROJECT_NAME/app/artisan horizon | |
autostart=true | |
autorestart=true | |
user=www-data | |
redirect_stderr=false | |
stdout_logfile=/var/www/$PROJECT_NAME/app/storage/logs/horizon.log | |
stderr_logfile=/var/www/$PROJECT_NAME/app/storage/logs/horizon-error.log | |
stopwaitsecs=3600 | |
EOF | |
echo "Step 21: Updating Supervisor configuration..." | |
sudo supervisorctl reread | |
sudo supervisorctl update | |
echo "Step 22: Starting Supervisor services..." | |
sudo supervisorctl start ${PROJECT_NAME}_octane:* | |
sudo supervisorctl start ${PROJECT_NAME}_horizon:* | |
################ | |
### FINAL STEPS ### | |
################ | |
echo "================================================" | |
echo "Provisioning Complete!" | |
echo "================================================" | |
echo "Server IP: $(curl -4 -s icanhazip.com)" | |
echo "Project Location: /var/www/$PROJECT_NAME/app" | |
echo "Octane Port: $OCTANE_PORT" | |
echo "" | |
echo "Next Steps:" | |
echo "1. Configure your .env file in /var/www/$PROJECT_NAME/app" | |
echo "2. Run database migrations: php artisan migrate" | |
echo "3. Configure Nginx virtual host for your domain" | |
echo "4. Set up SSL certificates" | |
echo "" | |
echo "Supervisor Status:" | |
sudo supervisorctl status | |
echo "" | |
echo "Setup completed successfully!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment