# MCSS School Management System — Deployment Guide
# Monrovia Consolidated School System · Laravel 10

---

## PART A: cPanel Shared Hosting (Primary — Liberia Context)

Recommended hosts: Namecheap, Hostinger, A2 Hosting (with PHP 8.1+)

### 1. Prerequisites

Check your cPanel has:
- PHP 8.1 or 8.2 (set via "Select PHP Version" in cPanel)
- Required extensions: pdo_mysql, mbstring, openssl, tokenizer, xml, ctype, json, bcmath, gd
- MySQL 5.7+ or MariaDB 10.3+
- Composer (ask host if not available — or run locally and upload vendor/)
- SSH access (strongly recommended)

### 2. Upload Files

Option A — SSH (preferred):
```bash
# SSH into your cPanel server
ssh username@yourhost.com

# Navigate to home directory
cd ~

# Clone or upload zip and extract into a private directory
# IMPORTANT: Do NOT place Laravel in public_html — only the /public folder goes there

mkdir mcss_app
cd mcss_app
# Upload your project files here (via SFTP or git clone)
```

Option B — SFTP (FileZilla):
- Upload entire project to: /home/yourusername/mcss_app/
- Do NOT upload vendor/ (too many small files — composer install on server instead)

### 3. Point public_html to Laravel /public

In cPanel → Domains → your domain → Document Root:
Set to: /home/yourusername/mcss_app/public

OR (if you can't change document root):
```bash
# Move contents of /public into public_html and update index.php paths
cp public_html/index.php public_html/index.php.bak

# Edit public_html/index.php — update these two lines:
require __DIR__.'/../mcss_app/vendor/autoload.php';
$app = require_once __DIR__.'/../mcss_app/bootstrap/app.php';
```

### 4. Create MySQL Database

cPanel → MySQL Databases:
1. Create database: mcss_prod
2. Create user: mcss_user (strong password)
3. Add user to database with ALL PRIVILEGES
4. Note host (usually: localhost or 127.0.0.1)

### 5. Configure .env

```bash
cd ~/mcss_app
cp .env.example .env
nano .env
```

```dotenv
APP_NAME="MCSS School Portal"
APP_ENV=production
APP_KEY=                        # Will be generated next
APP_DEBUG=false
APP_URL=https://yourdomain.edu.lr

LOG_CHANNEL=daily
LOG_LEVEL=error

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=mcss_prod
DB_USERNAME=mcss_user
DB_PASSWORD=your_strong_password_here

CACHE_DRIVER=file               # No Redis on shared hosting
QUEUE_CONNECTION=sync           # No queue workers on shared hosting
SESSION_DRIVER=file
SESSION_LIFETIME=480
SESSION_SECURE_COOKIE=true

FILESYSTEM_DISK=local

MAIL_MAILER=smtp
MAIL_HOST=mail.yourdomain.edu.lr
MAIL_PORT=465
MAIL_USERNAME=noreply@yourdomain.edu.lr
MAIL_PASSWORD=your_mail_password
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS="noreply@yourdomain.edu.lr"
MAIL_FROM_NAME="MCSS Portal"
```

### 6. Install Dependencies & Run Migrations

```bash
cd ~/mcss_app

# Generate app key
php artisan key:generate

# Install composer packages
composer install --no-dev --optimize-autoloader

# Run database migrations
php artisan migrate --force

# Seed with initial data (creates super admin + sample schools)
php artisan db:seed --force

# Create storage symlink
php artisan storage:link

# Cache config/routes for performance
php artisan config:cache
php artisan route:cache
php artisan view:cache
```

### 7. File Permissions

```bash
chmod -R 755 ~/mcss_app
chmod -R 775 ~/mcss_app/storage
chmod -R 775 ~/mcss_app/bootstrap/cache
chown -R www-data:www-data ~/mcss_app/storage   # Adjust user to your host's web user
```

### 8. Transcript PDF Storage

Transcripts are saved to storage/app/public/transcripts/
The storage:link command creates the symlink: public/storage → storage/app/public

Ensure this directory exists:
```bash
mkdir -p ~/mcss_app/storage/app/public/transcripts
chmod -R 775 ~/mcss_app/storage/app/public/transcripts
```

### 9. cPanel Cron Jobs (Optional — for scheduled tasks)

cPanel → Cron Jobs → Add Cron Job:
- Every minute: */1 * * * * /usr/local/bin/php ~/mcss_app/artisan schedule:run >> /dev/null 2>&1

### 10. First Login

URL: https://yourdomain.edu.lr/login
Super Admin: admin@mcss.edu.lr / password

⚠️  CHANGE DEFAULT PASSWORDS IMMEDIATELY after first login.

---

## PART B: VPS / Cloud Deployment (Recommended for Production)

Providers: DigitalOcean, AWS Lightsail, Vultr, Hetzner
Minimum: 1 vCPU, 1GB RAM, 25GB SSD — Ubuntu 22.04 LTS

### Server Setup

```bash
# Update system
sudo apt update && sudo apt upgrade -y

# Install LEMP stack
sudo apt install nginx mysql-server php8.2-fpm \
    php8.2-mysql php8.2-mbstring php8.2-xml php8.2-zip \
    php8.2-gd php8.2-bcmath php8.2-curl php8.2-dom \
    unzip curl git -y

# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

# Install Node (for any future npm use)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -
sudo apt install nodejs -y
```

### Nginx Configuration

```nginx
# /etc/nginx/sites-available/mcss
server {
    listen 80;
    server_name yourdomain.edu.lr www.yourdomain.edu.lr;
    root /var/www/mcss/public;
    index index.php index.html;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    add_header X-XSS-Protection "1; mode=block";

    # Gzip (critical for low-bandwidth Liberia context)
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml;
    gzip_min_length 1000;
    gzip_comp_level 6;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.ht { deny all; }

    # Cache static assets aggressively (CDN assets already handled by Bootstrap CDN)
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Block direct access to sensitive files
    location ~ /\.(env|git|htaccess) { deny all; }

    client_max_body_size 20M;
}
```

```bash
sudo ln -s /etc/nginx/sites-available/mcss /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
```

### SSL Certificate (Free — Let's Encrypt)

```bash
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.edu.lr -d www.yourdomain.edu.lr
```

### Deploy Application

```bash
sudo mkdir -p /var/www/mcss
sudo chown -R $USER:$USER /var/www/mcss

git clone https://github.com/your-repo/mcss.git /var/www/mcss
cd /var/www/mcss

composer install --no-dev --optimize-autoloader
cp .env.example .env
# Edit .env with production values
nano .env

php artisan key:generate
php artisan migrate --force
php artisan db:seed --force
php artisan storage:link
php artisan config:cache && php artisan route:cache && php artisan view:cache

sudo chown -R www-data:www-data storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cache
```

### MySQL Hardening

```bash
sudo mysql_secure_installation

# Create dedicated DB user
sudo mysql -u root -p
CREATE DATABASE mcss_production CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mcss_user'@'localhost' IDENTIFIED BY 'StrongPasswordHere!';
GRANT ALL PRIVILEGES ON mcss_production.* TO 'mcss_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
```

### Queue Worker (with Supervisor)

```bash
sudo apt install supervisor -y

# /etc/supervisor/conf.d/mcss-worker.conf
[program:mcss-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/mcss/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/mcss/storage/logs/worker.log
stopwaitsecs=3600

sudo supervisorctl reread && sudo supervisorctl update && sudo supervisorctl start all
```

---

## PART C: Low-Bandwidth Optimisations (Liberia Context)

The system already uses CDN-only assets (no local npm/Vite build):

1. Bootstrap 5.3 CSS/JS via jsDelivr CDN
2. Chart.js via jsDelivr CDN
3. Bootstrap Icons via jsDelivr CDN
4. All icons are web fonts (cached after first load)

Additional recommendations:
- Enable Nginx gzip (configured above)
- Set aggressive browser caching headers (configured above)
- Compress uploaded photos server-side with Intervention Image
- Use pagination (already implemented — 25 students/page)
- Avoid loading all records without pagination
- Transcript PDFs are generated on-demand and cached to storage

### Offline Fallback (Future Enhancement)

For extremely low-bandwidth environments, consider:
- Service Worker caching of the UI shell
- IndexedDB for offline grade entry (sync on reconnect)
- Progressive Web App (PWA) manifest

---

## PART D: Backup Strategy

```bash
# /etc/cron.d/mcss-backup
0 2 * * * www-data /usr/local/bin/php /var/www/mcss/artisan app:backup >> /dev/null 2>&1

# Manual database backup
mysqldump -u mcss_user -p mcss_production | gzip > backup_$(date +%Y%m%d).sql.gz

# Store off-site (e.g., S3-compatible storage — Backblaze B2 is affordable)
```

---

## Post-Deployment Checklist

- [ ] APP_DEBUG=false in .env
- [ ] Change all default passwords (admin@mcss.edu.lr, school admins)
- [ ] SSL certificate installed and auto-renewing
- [ ] Storage symlink working (test transcript PDF generation)
- [ ] Email (SMTP) working — test via tinker: Mail::raw('test', fn($m) => $m->to('you@test.com'))
- [ ] Cron job configured for scheduled tasks
- [ ] Backups configured and tested
- [ ] Grading scales configured per school (or MCSS default applied)
- [ ] First academic session and terms created per school
- [ ] Grade levels and class arms set up per school

---

Default Credentials (CHANGE IMMEDIATELY):
  Super Admin:  admin@mcss.edu.lr         / password
  School Admin: admin@GWG.edu.lr          / password
  Registrar:    registrar@GWG.edu.lr      / password
  Teacher:      teacher@GWG.edu.lr        / password
