diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..8154bf1 --- /dev/null +++ b/install.sh @@ -0,0 +1,171 @@ +#!/bin/bash + +# URLs for configuration files +DOCKER_COMPOSE_URL="https://git.masscivicdynamic.com/masscivicdynamic/nexo-cloud-scripts/raw/branch/main/docker-compose.yml" +KUBERNETES_DEPLOY_URL="https://git.masscivicdynamic.com/masscivicdynamic/nexo-cloud-scripts/raw/branch/main/kube-deploy.yaml" +ENV_FILE="/data/nexo-cloud/.env" + +# Minimum disk space requirements (in GB) +MIN_TOTAL_DISK_SPACE=30 +MIN_AVAILABLE_DISK_SPACE=20 + +# Function to check if a command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Function to generate a random password +generate_random_password() { + echo "$(openssl rand -base64 16)" +} + +# Function to generate a new APP_KEY +generate_app_key() { + echo "$(openssl rand -base64 32)" +} + +# Function to check disk space requirements +check_disk_space() { + local total_space=$(df --output=size /data | tail -n 1 | awk '{print $1}') + local available_space=$(df --output=avail /data | tail -n 1 | awk '{print $1}') + local total_space_gb=$((total_space / 1024 / 1024)) + local available_space_gb=$((available_space / 1024 / 1024)) + + if [ "$total_space_gb" -lt "$MIN_TOTAL_DISK_SPACE" ]; then + echo "Error: Total disk space is less than $MIN_TOTAL_DISK_SPACE GB." + exit 1 + fi + + if [ "$available_space_gb" -lt "$MIN_AVAILABLE_DISK_SPACE" ]; then + echo "Error: Available disk space is less than $MIN_AVAILABLE_DISK_SPACE GB." + exit 1 + fi +} + +# Function to handle the .env file +handle_env_file() { + if [ ! -f "$ENV_FILE" ]; then + echo "No .env file found. Creating a new one." + mkdir -p "$(dirname "$ENV_FILE")" + touch "$ENV_FILE" + fi + + # Generate and append variables + APP_KEY=$(generate_app_key) + APP_NAME="NexoCloud" + DB_USERNAME="nexo-cloud" + DB_PASSWORD=$(generate_random_password) + REDIS_PASSWORD=$(generate_random_password) + + # Set APP_NAME + if ! grep -q "^APP_NAME=" "$ENV_FILE"; then + echo "APP_NAME=$APP_NAME" >> "$ENV_FILE" + echo "Default APP_NAME set to $APP_NAME." + fi + + # Handle APP_PREVIOUS_KEYS and APP_KEY + if grep -q "^APP_KEY=" "$ENV_FILE"; then + PREVIOUS_KEYS=$(grep "^APP_PREVIOUS_KEYS=" "$ENV_FILE" | cut -d'=' -f2) + NEW_PREVIOUS_KEYS="${PREVIOUS_KEYS},$(grep "^APP_KEY=" "$ENV_FILE" | cut -d'=' -f2)" + sed -i '/^APP_PREVIOUS_KEYS=/d' "$ENV_FILE" + echo "APP_PREVIOUS_KEYS=$NEW_PREVIOUS_KEYS" >> "$ENV_FILE" + else + echo "APP_PREVIOUS_KEYS=$APP_KEY" >> "$ENV_FILE" + fi + sed -i '/^APP_KEY=/d' "$ENV_FILE" + echo "APP_KEY=$APP_KEY" >> "$ENV_FILE" + + # Set DB_USERNAME if not present + if ! grep -q "^DB_USERNAME=" "$ENV_FILE"; then + echo "DB_USERNAME=$DB_USERNAME" >> "$ENV_FILE" + echo "Default DB_USERNAME set to $DB_USERNAME." + fi + + # Set DB_PASSWORD if not present + if ! grep -q "^DB_PASSWORD=" "$ENV_FILE"; then + echo "DB_PASSWORD=$DB_PASSWORD" >> "$ENV_FILE" + echo "Generated DB_PASSWORD." + fi + + # Set REDIS_PASSWORD if not present + if ! grep -q "^REDIS_PASSWORD=" "$ENV_FILE"; then + echo "REDIS_PASSWORD=$REDIS_PASSWORD" >> "$ENV_FILE" + echo "Generated REDIS_PASSWORD." + fi + + echo "Environment variables set up in $ENV_FILE." +} + +# Function to load the .env file +load_env_file() { + if [ -f "$ENV_FILE" ]; then + export $(grep -v '^#' "$ENV_FILE" | xargs) + echo "Environment variables loaded from $ENV_FILE." + else + echo "No .env file found. Exiting." + exit 1 + fi +} + +# Main installation logic +install_application() { + check_disk_space + handle_env_file + load_env_file + + if command_exists docker; then + echo "Docker detected. Proceeding with Docker setup..." + curl -o docker-compose.yml $DOCKER_COMPOSE_URL + echo "docker-compose.yml downloaded successfully." + echo "Running Docker Compose with the environment variables..." + docker-compose --env-file "$ENV_FILE" up -d + elif command_exists kubectl || command_exists k3s; then + echo "K3s or Kubernetes detected. Proceeding with Kubernetes setup..." + curl -o kubernetes-deploy.yaml $KUBERNETES_DEPLOY_URL + echo "kubernets-deploy.yaml downloaded successfully." + echo "Applying Kubernetes deployment..." + kubectl apply -f kubernetes-deploy.yaml + else + echo "Neither Docker nor Kubernetes is installed." + read -p "Would you like to install Docker or K3s? (docker/k3s): " choice + case "$choice" in + docker) + install_docker + curl -o docker-compose.yml $DOCKER_COMPOSE_URL + echo "docker-compose.yml downloaded successfully." + echo "Running Docker Compose with the environment variables..." + docker-compose --env-file "$ENV_FILE" up -d + ;; + k3s) + install_k3s + curl -o kubernetes-deploy.yaml $KUBERNETES_DEPLOY_URL + echo "kubernets-deploy.yaml downloaded successfully." + echo "Applying Kubernetes deployment..." + kubectl apply -f kubernetes-deploy.yaml + ;; + *) + echo "Invalid choice. Exiting." + exit 1 + ;; + esac + fi +} + +# Function to install Docker +install_docker() { + echo "Docker is not installed. Installing Docker..." + curl -fsSL https://get.docker.com | bash + sudo systemctl start docker + sudo systemctl enable docker + echo "Docker installed successfully." +} + +# Function to install K3s +install_k3s() { + echo "K3s is not installed. Installing K3s..." + curl -sfL https://get.k3s.io | sh - + echo "K3s installed successfully." +} + +# Run the installation process +install_application diff --git a/kube-deploy.yaml b/kube-deploy.yaml new file mode 100644 index 0000000..c358379 --- /dev/null +++ b/kube-deploy.yaml @@ -0,0 +1,235 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nexo-cloud + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: postgres-data + namespace: nexo-cloud +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: nexo-cloud-storage + namespace: nexo-cloud +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 5Gi + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nexo-cloud + namespace: nexo-cloud +spec: + replicas: 2 + selector: + matchLabels: + app: nexo-cloud + template: + metadata: + labels: + app: nexo-cloud + spec: + containers: + - name: nexo-cloud + image: git.masscivicdynamic.com/masscivicdynamic/nexo-cloud:latest + ports: + - containerPort: 8000 + env: + - name: APP_ENV + value: production + - name: APP_KEY + valueFrom: + secretKeyRef: + name: nexo-cloud-secret + key: app-key + - name: DB_HOST + value: postgres + - name: DB_PORT + value: "5432" + - name: DB_DATABASE + value: laravel + - name: DB_USERNAME + valueFrom: + secretKeyRef: + name: nexo-cloud-db-secret + key: username + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: nexo-cloud-db-secret + key: password + - name: REDIS_HOST + value: redis + - name: REDIS_PORT + value: "6379" + volumeMounts: + - name: storage + mountPath: /var/www/html/storage + volumes: + - name: storage + persistentVolumeClaim: + claimName: nexo-cloud-storage + +--- +apiVersion: v1 +kind: Service +metadata: + name: nexo-cloud-service + namespace: nexo-cloud +spec: + selector: + app: laravel + ports: + - protocol: TCP + port: 80 + targetPort: 8000 + type: LoadBalancer + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + namespace: nexo-cloud +spec: + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:16 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: laravel + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + name: nexo-cloud-db-secret + key: username + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: nexo-cloud-db-secret + key: password + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: postgres-data + +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: nexo-cloud +spec: + selector: + app: postgres + ports: + - protocol: TCP + port: 5432 + targetPort: 5432 + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis + namespace: nexo-cloud +spec: + replicas: 1 + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis + image: redis:7.2 + ports: + - containerPort: 6379 + +--- +apiVersion: v1 +kind: Service +metadata: + name: redis + namespace: nexo-cloud +spec: + selector: + app: redis + ports: + - protocol: TCP + port: 6379 + targetPort: 6379 + type: ClusterIP + +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: nexo-cloud-scheduler + namespace: nexo-cloud +spec: + schedule: "*/5 * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: scheduler + image: git.masscivicdynamic.com/masscivicdynamic/nexo-cloud:latest + command: ["php", "/var/www/html/artisan", "schedule:run"] + restartPolicy: OnFailure + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nexo-cloud-worker + namespace: nexo-cloud +spec: + replicas: 2 + selector: + matchLabels: + app: nexo-cloud-worker + template: + metadata: + labels: + app: nexo-cloud-worker + spec: + containers: + - name: worker + image: git.masscivicdynamic.com/masscivicdynamic/nexo-cloud:latest + command: ["php", "/var/www/html/artisan", "queue:work", "--tries=3"]