Last active
May 20, 2024 10:41
-
-
Save heychazza/6a77c5870706d752468bf12ff8dbb88c to your computer and use it in GitHub Desktop.
Configures a VPS with everything needed to run a Laravel app.
This file contains 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 | |
# Prompt user for app domain | |
read -p "Enter the app domain (default: staging.analyse.net): " APP_DOMAIN | |
APP_DOMAIN="${APP_DOMAIN:-staging.analyse.net}" | |
# Prompt user for Git repository | |
read -p "Enter the Git repository (default: track/analytics.tebex.io): " GIT_REPO | |
GIT_REPO="${GIT_REPO:-track/analytics.tebex.io}" | |
# Prompt user for PHP version | |
read -p "Enter the PHP version (default: 8.2): " PHP_VERSION | |
PHP_VERSION="${PHP_VERSION:-8.2}" | |
# Prompt user for email | |
read -p "Enter your email: " EMAIL | |
# Prompt user for Node.js version | |
read -p "Enter the Node.js version (default: 18): " NODE_MAJOR | |
NODE_MAJOR="${NODE_MAJOR:-18}" | |
# Prompt user if they want to lock down the machine to a specific IP | |
read -p "Do you want to lock down the machine to a specific IP? (y/n): " LOCK_IP | |
if [ "$LOCK_IP" == "y" ]; then | |
read -p "Enter the IP address: " VPN_IP | |
fi | |
PUBLIC_IP=$(curl api.ipify.org) | |
# Update system | |
sudo apt upgrade -y | |
sudo apt update -y | |
export COMPOSER_ALLOW_SUPERUSER=1 | |
# PHP installation | |
sudo apt install lsb-release apt-transport-https ca-certificates software-properties-common -y | |
sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg | |
sudo sh -c "echo 'deb https://packages.sury.org/php/ $(lsb_release -sc) main' > /etc/apt/sources.list.d/php.list" | |
sudo apt update | |
sudo apt install php$PHP_VERSION php$PHP_VERSION-{cli,zip,mysql,fpm,bz2,curl,mbstring,intl,redis,dom,common} -y | |
systemctl enable php$PHP_VERSION-fpm | |
systemctl start php$PHP_VERSION-fpm | |
export PHP_INI_PATH="/etc/php/$PHP_VERSION/fpm/php.ini" | |
sed -i 's/max_execution_time = 30/max_execution_time = 180/' $PHP_INI_PATH | |
sed -i 's/memory_limit = 128M/memory_limit = 512M/' $PHP_INI_PATH | |
sudo systemctl restart php$PHP_VERSION-fpm | |
# Composer installation | |
cd ~ | |
curl -sS https://getcomposer.org/installer -o composer-setup.php | |
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer | |
rm -rf composer-setup.php | |
# Node.js and Yarn installation | |
sudo apt update | |
sudo apt install -y ca-certificates curl gnupg | |
sudo mkdir -p /etc/apt/keyrings | |
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg | |
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list | |
sudo apt update | |
sudo apt install nodejs -y | |
npm install --global yarn | |
# Git installation and configuration | |
sudo apt install git -y | |
ssh-keygen -t ed25519 -C "$EMAIL" | |
eval "$(ssh-agent -s)" | |
git config --global pull.rebase false | |
echo "Add the following key to your GitHub (https://github.com/settings/ssh/new)..." | |
cat ~/.ssh/id_ed25519.pub | |
echo "" | |
echo "Then press any key to continue." | |
# Wait for a key press to continue | |
read -s -n 1 | |
# Project setup | |
git clone git@github.com:$GIT_REPO.git /var/www/$APP_DOMAIN | |
cd /var/www/$APP_DOMAIN | |
composer install --no-interaction --prefer-dist --optimize-autoloader --no-dev | |
yarn install --prod | |
cp -rf .env.example .env | |
yarn build | |
setfacl -R -m g:www-data:rwx /var/www/ | |
# Add Cronjob | |
(crontab -l; echo "* * * * * cd /var/www/$APP_DOMAIN && php artisan schedule:run >> /dev/null 2>&1") | awk '!x[$0]++' | crontab - | |
# Nginx configuration | |
sudo apt install ufw nginx -y | |
# Path to the update_proxies.sh script | |
UPDATE_SCRIPT="~/scripts/update_proxies.sh" | |
# Create the update_proxies.sh script | |
cat << 'EOF' > $UPDATE_SCRIPT | |
#!/bin/bash | |
# Define the URLs for the Cloudflare IP lists | |
IPV4_URL="https://www.cloudflare.com/ips-v4/" | |
IPV6_URL="https://www.cloudflare.com/ips-v6/" | |
# Fetch the IP lists | |
IPV4_LIST=$(curl -s $IPV4_URL) | |
IPV6_LIST=$(curl -s $IPV6_URL) | |
# Prepare the Nginx configuration content | |
CF_PROXIES="# Cloudflare IPs\n" | |
# Add the IPv4 addresses | |
for IP in $IPV4_LIST; do | |
CF_PROXIES+="set_real_ip_from $IP;\n" | |
done | |
# Add the IPv6 addresses | |
for IP in $IPV6_LIST; do | |
CF_PROXIES+="set_real_ip_from $IP;\n" | |
done | |
# Add the real_ip_header directive | |
CF_PROXIES+="real_ip_header CF-Connecting-IP;" | |
# Write the configuration to the file | |
echo -e "$CF_PROXIES" > "/etc/nginx/snippets/proxies.conf" | |
# Reload Nginx to apply the new configuration | |
nginx -t && nginx -s reload | |
EOF | |
# Make the update_proxies.sh script executable | |
chmod +x $UPDATE_SCRIPT | |
# Add the cron job to run the update_proxies.sh script weekly | |
(crontab -l 2>/dev/null; echo "0 0 * * 0 $UPDATE_SCRIPT") | crontab - | |
CONFIG="server { | |
server_name $APP_DOMAIN; | |
root /var/www/$APP_DOMAIN/public; | |
add_header X-Frame-Options "SAMEORIGIN"; | |
add_header X-Content-Type-Options "nosniff"; | |
real_ip_header X-Forwarded-For; | |
include /etc/nginx/snippets/proxies.conf; | |
ssl_client_certificate /etc/ssl/certs/cloudflare.crt; | |
ssl_verify_client on; | |
index index.php; | |
fastcgi_buffers 16 16k; | |
fastcgi_buffer_size 32k; | |
proxy_buffer_size 128k; | |
proxy_buffers 4 256k; | |
proxy_busy_buffers_size 256k; | |
charset utf-8; | |
client_max_body_size 4M; | |
location / { | |
try_files $uri $uri/ /index.php?$query_string; | |
} | |
location = /favicon.ico { access_log off; log_not_found off; } | |
location = /robots.txt { access_log off; log_not_found off; } | |
error_page 404 /index.php; | |
location ~ \.php$ { | |
include snippets/fastcgi-php.conf; | |
fastcgi_pass unix:/var/run/php/php$PHP_VERSION-fpm.sock; | |
} | |
}" | |
echo "$CONFIG" > "/etc/nginx/sites-available/$APP_DOMAIN.conf" | |
sudo ln -s /etc/nginx/sites-available/$APP_DOMAIN.conf /etc/nginx/sites-enabled | |
sudo curl -L https://developers.cloudflare.com/ssl/static/authenticated_origin_pull_ca.pem -o /etc/ssl/certs/cloudflare.crt | |
nginx -s reload | |
ufw allow 'Nginx Full' | |
# Firewall configuration | |
if [ "$LOCK_IP" == "y" ]; then | |
ufw allow from $VPN_IP to any port 8080 | |
ufw allow from $VPN_IP to any port 8081 | |
ufw allow from $VPN_IP to any port 3306 | |
ufw allow from $VPN_IP to any port 22 | |
else | |
ufw allow 8080/tcp | |
ufw allow 8081/tcp | |
ufw allow 3306/tcp | |
ufw allow 22/tcp | |
fi | |
# Enable the firewall | |
ufw enable | |
# LetsEncrypt | |
sudo apt install certbot python3-certbot-nginx -y | |
sudo certbot --nginx --non-interactive --agree-tos -m $EMAIL -d $APP_DOMAIN | |
# Redis installation and configuration | |
sudo apt install redis-server -y | |
sudo systemctl enable redis-server.service | |
sudo systemctl start redis-server.service | |
# Supervisor installation and configuration | |
sudo apt install supervisor | |
sudo systemctl enable supervisor.service | |
sudo systemctl start supervisor.service | |
# Define the content of the file | |
CONTENT="[program:horizon] | |
process_name=%(program_name)s | |
command=php /var/www/$APP_DOMAIN/artisan horizon | |
autostart=true | |
autorestart=true | |
user=root | |
redirect_stderr=true | |
stdout_logfile=/var/www/$APP_DOMAIN/horizon.log | |
stopwaitsecs=3600" | |
echo "$CONTENT" > "/etc/supervisor/conf.d/horizon.conf" | |
sudo supervisorctl reread | |
sudo supervisorctl update | |
sudo supervisorctl start "horizon:*" | |
# SingleStore installation | |
wget -O - 'https://release.memsql.com/release-aug2018.gpg' 2>/dev/null | sudo apt-key add - && apt-key list | |
apt-cache policy apt-transport-https | |
echo "deb [arch=amd64] https://release.memsql.com/production/debian memsql main" | sudo tee /etc/apt/sources.list.d/memsql.list | |
sudo apt update && sudo apt -y install singlestoredb-toolbox singlestoredb-studio | |
sudo systemctl start singlestoredb-studio | |
sudo systemctl enable singlestoredb-studio.service | |
# Function to calculate min_free_kbytes based on system RAM | |
calculate_min_free_kbytes() { | |
total_ram_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}') | |
min_free_kb=$((total_ram_kb / 100)) # 1% of total RAM | |
if (( min_free_kb > 4000000 )); then | |
min_free_kb=4000000 # Cap at 4 GB | |
fi | |
echo $min_free_kb | |
} | |
# Set recommended vm settings (According to SingleStore) | |
echo "Setting recommended vm settings..." | |
sudo sysctl -w vm.max_map_count=1000000000 | |
sudo sysctl -w vm.overcommit_memory=0 | |
sudo sysctl -w vm.swappiness=10 | |
sudo sysctl -w vm.overcommit_ratio=99 # Only if vm.overcommit_memory is set to 2 | |
sudo sysctl -w net.core.rmem_max=8388606 | |
sudo sysctl -w net.core.wmem_max=8388606 | |
# Calculate min_free_kbytes | |
min_free_kbytes=$(calculate_min_free_kbytes) | |
# Set min_free_kbytes | |
sudo sysctl -w vm.min_free_kbytes=$min_free_kbytes | |
# Prompt user for SingleStore key | |
read -p "Enter your SingleStore license key (from portal.singlestore.com): " SINGLESTORE_KEY | |
CLUSTER_YAML="license: $SINGLESTORE_KEY | |
high_availability: false | |
memsql_server_version: 8.5.15 | |
hosts: | |
- hostname: $PUBLIC_IP | |
nodes: | |
- role: Master | |
config: | |
port: 3306 | |
- role: Leaf | |
config: | |
port: 3307 | |
localhost: true" | |
echo "$CLUSTER_YAML" > "cluster.yml" | |
sdb-deploy setup-cluster --cluster-file cluster.yml | |
rm -rf install-dedi.sh cluster.yml |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
RUN USING:
curl -L https://gist.githubusercontent.com/heychazza/6a77c5870706d752468bf12ff8dbb88c/raw/install-dedi.sh -o install-dedi.sh