templave v1
This commit is contained in:
92
deploy/apache/apache-setup.md
Normal file
92
deploy/apache/apache-setup.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Apache Virtual Host Setup for Laravel
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Ubuntu 24.04 with Apache2 and PHP-FPM installed.
|
||||
|
||||
## Required Apache Modules
|
||||
|
||||
Enable the necessary modules:
|
||||
|
||||
```bash
|
||||
sudo a2enmod rewrite
|
||||
sudo a2enmod headers
|
||||
sudo a2enmod ssl
|
||||
sudo a2enmod proxy_fcgi
|
||||
sudo a2enmod deflate
|
||||
sudo a2enmod expires
|
||||
sudo a2enmod setenvif
|
||||
```
|
||||
|
||||
## Installation Steps
|
||||
|
||||
### 1. Copy Virtual Host Configuration
|
||||
|
||||
```bash
|
||||
sudo cp deploy/apache/laravel-site.conf /etc/apache2/sites-available/your-app.conf
|
||||
```
|
||||
|
||||
### 2. Edit Configuration
|
||||
|
||||
Update the following in the config file:
|
||||
- `ServerName` - Your domain name
|
||||
- `DocumentRoot` - Path to Laravel's public folder
|
||||
- `Directory` - Same path as DocumentRoot
|
||||
- Log file names
|
||||
|
||||
### 3. Enable Site
|
||||
|
||||
```bash
|
||||
sudo a2ensite your-app.conf
|
||||
sudo a2dissite 000-default.conf # Disable default site if needed
|
||||
```
|
||||
|
||||
### 4. Test Configuration
|
||||
|
||||
```bash
|
||||
sudo apache2ctl configtest
|
||||
```
|
||||
|
||||
### 5. Restart Apache
|
||||
|
||||
```bash
|
||||
sudo systemctl restart apache2
|
||||
```
|
||||
|
||||
## SSL with Certbot
|
||||
|
||||
Install Certbot and obtain SSL certificate:
|
||||
|
||||
```bash
|
||||
sudo apt install certbot python3-certbot-apache
|
||||
sudo certbot --apache -d your-domain.com -d www.your-domain.com
|
||||
```
|
||||
|
||||
Certbot will automatically modify your Apache configuration for SSL.
|
||||
|
||||
## File Permissions
|
||||
|
||||
Set correct permissions for Laravel:
|
||||
|
||||
```bash
|
||||
sudo chown -R www-data:www-data /var/www/your-app
|
||||
sudo chmod -R 755 /var/www/your-app
|
||||
sudo chmod -R 775 /var/www/your-app/storage
|
||||
sudo chmod -R 775 /var/www/your-app/bootstrap/cache
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### 403 Forbidden
|
||||
- Check directory permissions
|
||||
- Ensure `AllowOverride All` is set
|
||||
- Verify `mod_rewrite` is enabled
|
||||
|
||||
### 500 Internal Server Error
|
||||
- Check Laravel logs: `storage/logs/laravel.log`
|
||||
- Check Apache error logs: `/var/log/apache2/your-app-error.log`
|
||||
- Ensure `.env` file exists and has correct permissions
|
||||
|
||||
### PHP Not Processing
|
||||
- Verify PHP-FPM is running: `sudo systemctl status php8.3-fpm`
|
||||
- Check socket path matches in Apache config
|
||||
115
deploy/apache/laravel-site.conf
Normal file
115
deploy/apache/laravel-site.conf
Normal file
@@ -0,0 +1,115 @@
|
||||
<VirtualHost *:80>
|
||||
ServerName your-domain.com
|
||||
ServerAlias www.your-domain.com
|
||||
ServerAdmin webmaster@your-domain.com
|
||||
|
||||
DocumentRoot /var/www/your-app/public
|
||||
|
||||
<Directory /var/www/your-app/public>
|
||||
Options -Indexes +FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
# PHP-FPM configuration
|
||||
<FilesMatch \.php$>
|
||||
SetHandler "proxy:unix:/var/run/php/php8.3-fpm.sock|fcgi://localhost"
|
||||
</FilesMatch>
|
||||
|
||||
# Security headers
|
||||
Header always set X-Frame-Options "SAMEORIGIN"
|
||||
Header always set X-Content-Type-Options "nosniff"
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
|
||||
# Disable server signature
|
||||
ServerSignature Off
|
||||
|
||||
# Logging
|
||||
ErrorLog ${APACHE_LOG_DIR}/your-app-error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/your-app-access.log combined
|
||||
|
||||
# Compression
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
|
||||
AddOutputFilterByType DEFLATE application/javascript application/json
|
||||
AddOutputFilterByType DEFLATE application/xml application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE image/svg+xml
|
||||
</IfModule>
|
||||
|
||||
# Static file caching
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
ExpiresByType image/jpeg "access plus 1 month"
|
||||
ExpiresByType image/png "access plus 1 month"
|
||||
ExpiresByType image/gif "access plus 1 month"
|
||||
ExpiresByType image/svg+xml "access plus 1 month"
|
||||
ExpiresByType text/css "access plus 1 month"
|
||||
ExpiresByType application/javascript "access plus 1 month"
|
||||
ExpiresByType font/woff2 "access plus 1 month"
|
||||
ExpiresByType font/woff "access plus 1 month"
|
||||
</IfModule>
|
||||
</VirtualHost>
|
||||
|
||||
# SSL Configuration (use with Let's Encrypt / Certbot)
|
||||
<VirtualHost *:443>
|
||||
ServerName your-domain.com
|
||||
ServerAlias www.your-domain.com
|
||||
ServerAdmin webmaster@your-domain.com
|
||||
|
||||
DocumentRoot /var/www/your-app/public
|
||||
|
||||
<Directory /var/www/your-app/public>
|
||||
Options -Indexes +FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
# PHP-FPM configuration
|
||||
<FilesMatch \.php$>
|
||||
SetHandler "proxy:unix:/var/run/php/php8.3-fpm.sock|fcgi://localhost"
|
||||
</FilesMatch>
|
||||
|
||||
# SSL Configuration (Certbot will fill these in)
|
||||
SSLEngine on
|
||||
SSLCertificateFile /etc/letsencrypt/live/your-domain.com/fullchain.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/your-domain.com/privkey.pem
|
||||
|
||||
# Modern SSL configuration
|
||||
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
|
||||
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
|
||||
SSLHonorCipherOrder off
|
||||
|
||||
# Security headers
|
||||
Header always set X-Frame-Options "SAMEORIGIN"
|
||||
Header always set X-Content-Type-Options "nosniff"
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
|
||||
ServerSignature Off
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/your-app-ssl-error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/your-app-ssl-access.log combined
|
||||
|
||||
# Compression
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
|
||||
AddOutputFilterByType DEFLATE application/javascript application/json
|
||||
AddOutputFilterByType DEFLATE application/xml application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE image/svg+xml
|
||||
</IfModule>
|
||||
|
||||
# Static file caching
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
ExpiresByType image/jpeg "access plus 1 month"
|
||||
ExpiresByType image/png "access plus 1 month"
|
||||
ExpiresByType image/gif "access plus 1 month"
|
||||
ExpiresByType image/svg+xml "access plus 1 month"
|
||||
ExpiresByType text/css "access plus 1 month"
|
||||
ExpiresByType application/javascript "access plus 1 month"
|
||||
ExpiresByType font/woff2 "access plus 1 month"
|
||||
ExpiresByType font/woff "access plus 1 month"
|
||||
</IfModule>
|
||||
</VirtualHost>
|
||||
77
deploy/nginx/laravel-site.conf
Normal file
77
deploy/nginx/laravel-site.conf
Normal file
@@ -0,0 +1,77 @@
|
||||
# Nginx site configuration for Laravel on Ubuntu 24.04
|
||||
# This config is for native Nginx (not Docker) behind Nginx Proxy Manager
|
||||
# Place this in /etc/nginx/sites-available/ and symlink to sites-enabled
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
# Replace with your domain or internal IP
|
||||
# Nginx Proxy Manager will forward traffic here
|
||||
server_name your-domain.com;
|
||||
|
||||
root /var/www/your-app/public;
|
||||
index index.php index.html index.htm;
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
charset utf-8;
|
||||
|
||||
# Laravel routing
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
# Favicon and robots
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location = /robots.txt { access_log off; log_not_found off; }
|
||||
|
||||
# Error pages
|
||||
error_page 404 /index.php;
|
||||
|
||||
# PHP-FPM configuration
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
|
||||
# Timeouts
|
||||
fastcgi_connect_timeout 60;
|
||||
fastcgi_send_timeout 180;
|
||||
fastcgi_read_timeout 180;
|
||||
fastcgi_buffer_size 128k;
|
||||
fastcgi_buffers 4 256k;
|
||||
fastcgi_busy_buffers_size 256k;
|
||||
}
|
||||
|
||||
# Deny access to hidden files
|
||||
location ~ /\.(?!well-known).* {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Static file caching
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|txt|woff|woff2|ttf|svg)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Gzip compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml application/xml+rss application/x-font-ttf font/opentype image/svg+xml;
|
||||
|
||||
client_max_body_size 100M;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/your-app-access.log;
|
||||
error_log /var/log/nginx/your-app-error.log;
|
||||
}
|
||||
79
deploy/nginx/nginx-proxy-manager-notes.md
Normal file
79
deploy/nginx/nginx-proxy-manager-notes.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Nginx Proxy Manager Configuration Notes
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
Internet → Nginx Proxy Manager (Docker/Host) → Native Nginx → PHP-FPM → Laravel
|
||||
↓
|
||||
SSL Termination
|
||||
(Let's Encrypt)
|
||||
```
|
||||
|
||||
## Nginx Proxy Manager Setup
|
||||
|
||||
### Option 1: NPM on Same Server
|
||||
If running NPM on the same Ubuntu 24.04 server:
|
||||
|
||||
1. **NPM listens on ports 80/443** (public)
|
||||
2. **Native Nginx listens on port 8080** (internal only)
|
||||
3. NPM forwards traffic to `localhost:8080`
|
||||
|
||||
Modify `laravel-site.conf`:
|
||||
```nginx
|
||||
server {
|
||||
listen 127.0.0.1:8080; # Only accept local connections
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Option 2: NPM on Separate Server
|
||||
If running NPM on a separate server:
|
||||
|
||||
1. Configure firewall to allow NPM server IP
|
||||
2. NPM forwards to `http://your-laravel-server-ip:80`
|
||||
|
||||
## NPM Proxy Host Configuration
|
||||
|
||||
In Nginx Proxy Manager web UI:
|
||||
|
||||
1. **Domain Names**: your-domain.com
|
||||
2. **Scheme**: http
|
||||
3. **Forward Hostname/IP**: 127.0.0.1 (or server IP)
|
||||
4. **Forward Port**: 8080 (or 80)
|
||||
5. **Enable**: Block Common Exploits
|
||||
6. **SSL Tab**:
|
||||
- Request new SSL Certificate
|
||||
- Force SSL
|
||||
- HTTP/2 Support
|
||||
|
||||
## Custom NPM Configuration
|
||||
|
||||
Add to "Advanced" tab if needed:
|
||||
|
||||
```nginx
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
|
||||
# WebSocket support (if using Laravel Echo/Reverb)
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
```
|
||||
|
||||
## Laravel Trusted Proxies
|
||||
|
||||
Update `app/Http/Middleware/TrustProxies.php` or configure in Laravel 11+:
|
||||
|
||||
```php
|
||||
// In bootstrap/app.php or config
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
$middleware->trustProxies(at: '*');
|
||||
})
|
||||
```
|
||||
|
||||
Or set in `.env`:
|
||||
```
|
||||
TRUSTED_PROXIES=*
|
||||
```
|
||||
62
deploy/production/.env.mysql.production
Normal file
62
deploy/production/.env.mysql.production
Normal file
@@ -0,0 +1,62 @@
|
||||
APP_NAME="Your App Name"
|
||||
APP_ENV=production
|
||||
APP_KEY=
|
||||
APP_DEBUG=false
|
||||
APP_TIMEZONE=UTC
|
||||
APP_URL=https://your-domain.com
|
||||
|
||||
APP_LOCALE=en
|
||||
APP_FALLBACK_LOCALE=en
|
||||
APP_FAKER_LOCALE=en_US
|
||||
|
||||
APP_MAINTENANCE_DRIVER=file
|
||||
APP_MAINTENANCE_STORE=database
|
||||
|
||||
BCRYPT_ROUNDS=12
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_STACK=single
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=error
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=your_database
|
||||
DB_USERNAME=your_db_user
|
||||
DB_PASSWORD=your_secure_password
|
||||
|
||||
SESSION_DRIVER=redis
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_ENCRYPT=true
|
||||
SESSION_PATH=/
|
||||
SESSION_DOMAIN=your-domain.com
|
||||
|
||||
BROADCAST_CONNECTION=log
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=redis
|
||||
|
||||
CACHE_STORE=redis
|
||||
CACHE_PREFIX=
|
||||
|
||||
REDIS_CLIENT=phpredis
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=smtp.your-provider.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=your_email_username
|
||||
MAIL_PASSWORD=your_email_password
|
||||
MAIL_ENCRYPTION=tls
|
||||
MAIL_FROM_ADDRESS="noreply@your-domain.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
TRUSTED_PROXIES=*
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
|
||||
# Error Logging - Flare (https://flareapp.io)
|
||||
# REQUIRED for production error tracking
|
||||
FLARE_KEY=your_flare_key_here
|
||||
62
deploy/production/.env.pgsql.production
Normal file
62
deploy/production/.env.pgsql.production
Normal file
@@ -0,0 +1,62 @@
|
||||
APP_NAME="Your App Name"
|
||||
APP_ENV=production
|
||||
APP_KEY=
|
||||
APP_DEBUG=false
|
||||
APP_TIMEZONE=UTC
|
||||
APP_URL=https://your-domain.com
|
||||
|
||||
APP_LOCALE=en
|
||||
APP_FALLBACK_LOCALE=en
|
||||
APP_FAKER_LOCALE=en_US
|
||||
|
||||
APP_MAINTENANCE_DRIVER=file
|
||||
APP_MAINTENANCE_STORE=database
|
||||
|
||||
BCRYPT_ROUNDS=12
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_STACK=single
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=error
|
||||
|
||||
DB_CONNECTION=pgsql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=5432
|
||||
DB_DATABASE=your_database
|
||||
DB_USERNAME=your_db_user
|
||||
DB_PASSWORD=your_secure_password
|
||||
|
||||
SESSION_DRIVER=redis
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_ENCRYPT=true
|
||||
SESSION_PATH=/
|
||||
SESSION_DOMAIN=your-domain.com
|
||||
|
||||
BROADCAST_CONNECTION=log
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=redis
|
||||
|
||||
CACHE_STORE=redis
|
||||
CACHE_PREFIX=
|
||||
|
||||
REDIS_CLIENT=phpredis
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=smtp.your-provider.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=your_email_username
|
||||
MAIL_PASSWORD=your_email_password
|
||||
MAIL_ENCRYPTION=tls
|
||||
MAIL_FROM_ADDRESS="noreply@your-domain.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
TRUSTED_PROXIES=*
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
|
||||
# Error Logging - Flare (https://flareapp.io)
|
||||
# REQUIRED for production error tracking
|
||||
FLARE_KEY=your_flare_key_here
|
||||
58
deploy/production/.env.sqlite.production
Normal file
58
deploy/production/.env.sqlite.production
Normal file
@@ -0,0 +1,58 @@
|
||||
APP_NAME="Your App Name"
|
||||
APP_ENV=production
|
||||
APP_KEY=
|
||||
APP_DEBUG=false
|
||||
APP_TIMEZONE=UTC
|
||||
APP_URL=https://your-domain.com
|
||||
|
||||
APP_LOCALE=en
|
||||
APP_FALLBACK_LOCALE=en
|
||||
APP_FAKER_LOCALE=en_US
|
||||
|
||||
APP_MAINTENANCE_DRIVER=file
|
||||
APP_MAINTENANCE_STORE=database
|
||||
|
||||
BCRYPT_ROUNDS=12
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_STACK=single
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=error
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=/var/www/your-app/database/database.sqlite
|
||||
|
||||
SESSION_DRIVER=redis
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_ENCRYPT=true
|
||||
SESSION_PATH=/
|
||||
SESSION_DOMAIN=your-domain.com
|
||||
|
||||
BROADCAST_CONNECTION=log
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=redis
|
||||
|
||||
CACHE_STORE=redis
|
||||
CACHE_PREFIX=
|
||||
|
||||
REDIS_CLIENT=phpredis
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=smtp.your-provider.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=your_email_username
|
||||
MAIL_PASSWORD=your_email_password
|
||||
MAIL_ENCRYPTION=tls
|
||||
MAIL_FROM_ADDRESS="noreply@your-domain.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
TRUSTED_PROXIES=*
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
|
||||
# Error Logging - Flare (https://flareapp.io)
|
||||
# REQUIRED for production error tracking
|
||||
FLARE_KEY=your_flare_key_here
|
||||
75
deploy/scripts/deploy.sh
Normal file
75
deploy/scripts/deploy.sh
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Laravel Deployment Script
|
||||
# Usage: ./deploy.sh /var/www/your-app [branch]
|
||||
|
||||
set -e
|
||||
|
||||
APP_PATH="${1:-/var/www/laravel}"
|
||||
BRANCH="${2:-main}"
|
||||
|
||||
if [ ! -d "$APP_PATH" ]; then
|
||||
echo "Error: Directory $APP_PATH does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$APP_PATH"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Deploying Laravel Application"
|
||||
echo "Path: $APP_PATH"
|
||||
echo "Branch: $BRANCH"
|
||||
echo "=========================================="
|
||||
|
||||
# Enable maintenance mode
|
||||
echo "[1/9] Enabling maintenance mode..."
|
||||
php artisan down --retry=60 || true
|
||||
|
||||
# Pull latest code
|
||||
echo "[2/9] Pulling latest changes..."
|
||||
git fetch origin
|
||||
git reset --hard origin/$BRANCH
|
||||
|
||||
# Install PHP dependencies
|
||||
echo "[3/9] Installing Composer dependencies..."
|
||||
composer install --no-dev --optimize-autoloader --no-interaction
|
||||
|
||||
# Install and build frontend assets
|
||||
echo "[4/9] Installing Node dependencies..."
|
||||
npm ci --production=false
|
||||
|
||||
echo "[5/9] Building frontend assets..."
|
||||
npm run build
|
||||
|
||||
# Run migrations
|
||||
echo "[6/9] Running database migrations..."
|
||||
php artisan migrate --force
|
||||
|
||||
# Clear and optimize
|
||||
echo "[7/9] Optimizing application..."
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
php artisan view:cache
|
||||
php artisan event:cache
|
||||
|
||||
# Fix permissions
|
||||
echo "[8/9] Fixing permissions..."
|
||||
sudo chown -R www-data:www-data storage bootstrap/cache
|
||||
sudo chmod -R 775 storage bootstrap/cache
|
||||
|
||||
# Restart services
|
||||
echo "[9/9] Restarting services..."
|
||||
sudo systemctl restart php8.3-fpm
|
||||
|
||||
# Restart queue workers if using Supervisor
|
||||
if [ -f /etc/supervisor/conf.d/laravel-worker.conf ]; then
|
||||
sudo supervisorctl restart laravel-worker:*
|
||||
fi
|
||||
|
||||
# Disable maintenance mode
|
||||
php artisan up
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Deployment complete!"
|
||||
echo "=========================================="
|
||||
43
deploy/scripts/fix-permissions.sh
Normal file
43
deploy/scripts/fix-permissions.sh
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Fix Laravel file permissions
|
||||
# Usage: ./fix-permissions.sh /var/www/your-app
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 /path/to/laravel/app"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APP_PATH="$1"
|
||||
|
||||
if [ ! -d "$APP_PATH" ]; then
|
||||
echo "Error: Directory $APP_PATH does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Fixing permissions for: $APP_PATH"
|
||||
|
||||
# Set ownership
|
||||
sudo chown -R www-data:www-data "$APP_PATH"
|
||||
|
||||
# Set directory permissions
|
||||
sudo find "$APP_PATH" -type d -exec chmod 755 {} \;
|
||||
|
||||
# Set file permissions
|
||||
sudo find "$APP_PATH" -type f -exec chmod 644 {} \;
|
||||
|
||||
# Make storage and cache writable
|
||||
sudo chmod -R 775 "$APP_PATH/storage"
|
||||
sudo chmod -R 775 "$APP_PATH/bootstrap/cache"
|
||||
|
||||
# Set ACL for current user to maintain access
|
||||
if command -v setfacl &> /dev/null; then
|
||||
sudo setfacl -Rm u:$(whoami):rwx "$APP_PATH/storage"
|
||||
sudo setfacl -Rm u:$(whoami):rwx "$APP_PATH/bootstrap/cache"
|
||||
sudo setfacl -dRm u:$(whoami):rwx "$APP_PATH/storage"
|
||||
sudo setfacl -dRm u:$(whoami):rwx "$APP_PATH/bootstrap/cache"
|
||||
fi
|
||||
|
||||
echo "Permissions fixed successfully!"
|
||||
6
deploy/scripts/laravel-scheduler.cron
Normal file
6
deploy/scripts/laravel-scheduler.cron
Normal file
@@ -0,0 +1,6 @@
|
||||
# Laravel Scheduler Cron Job
|
||||
# Add this to crontab: sudo crontab -e -u www-data
|
||||
# Or copy to /etc/cron.d/laravel-scheduler
|
||||
|
||||
# Run Laravel scheduler every minute
|
||||
* * * * * www-data cd /var/www/your-app && php artisan schedule:run >> /dev/null 2>&1
|
||||
202
deploy/scripts/server-setup.sh
Normal file
202
deploy/scripts/server-setup.sh
Normal file
@@ -0,0 +1,202 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Laravel Server Setup Script for Ubuntu 24.04
|
||||
# Run as root or with sudo
|
||||
|
||||
set -e
|
||||
|
||||
echo "=========================================="
|
||||
echo "Laravel Server Setup for Ubuntu 24.04"
|
||||
echo "=========================================="
|
||||
|
||||
# Update system
|
||||
echo "[1/8] Updating system packages..."
|
||||
apt update && apt upgrade -y
|
||||
|
||||
# Install essential packages
|
||||
echo "[2/8] Installing essential packages..."
|
||||
apt install -y \
|
||||
software-properties-common \
|
||||
curl \
|
||||
git \
|
||||
unzip \
|
||||
supervisor \
|
||||
acl
|
||||
|
||||
# Add PHP repository and install PHP 8.3
|
||||
echo "[3/8] Installing PHP 8.3 and extensions..."
|
||||
add-apt-repository -y ppa:ondrej/php
|
||||
apt update
|
||||
apt install -y \
|
||||
php8.3-fpm \
|
||||
php8.3-cli \
|
||||
php8.3-mysql \
|
||||
php8.3-pgsql \
|
||||
php8.3-sqlite3 \
|
||||
php8.3-redis \
|
||||
php8.3-mbstring \
|
||||
php8.3-xml \
|
||||
php8.3-curl \
|
||||
php8.3-zip \
|
||||
php8.3-bcmath \
|
||||
php8.3-intl \
|
||||
php8.3-gd \
|
||||
php8.3-imagick \
|
||||
php8.3-opcache
|
||||
|
||||
# Install Composer
|
||||
echo "[4/8] Installing Composer..."
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Install Node.js 20.x
|
||||
echo "[5/8] Installing Node.js 20.x..."
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||
apt install -y nodejs
|
||||
|
||||
# Database selection
|
||||
echo "[6/8] Database Installation..."
|
||||
echo ""
|
||||
echo "Select database server to install:"
|
||||
echo "1) MySQL 8.0"
|
||||
echo "2) PostgreSQL 16"
|
||||
echo "3) SQLite only (no server needed)"
|
||||
echo "4) Both MySQL and PostgreSQL"
|
||||
read -p "Enter choice [1-4]: " DB_CHOICE
|
||||
|
||||
case $DB_CHOICE in
|
||||
1)
|
||||
apt install -y mysql-server
|
||||
systemctl enable mysql
|
||||
systemctl start mysql
|
||||
echo "MySQL 8.0 installed."
|
||||
echo ""
|
||||
echo "To secure MySQL, run: sudo mysql_secure_installation"
|
||||
echo "To create database:"
|
||||
echo " sudo mysql"
|
||||
echo " CREATE DATABASE your_app;"
|
||||
echo " CREATE USER 'your_user'@'localhost' IDENTIFIED BY 'password';"
|
||||
echo " GRANT ALL PRIVILEGES ON your_app.* TO 'your_user'@'localhost';"
|
||||
echo " FLUSH PRIVILEGES;"
|
||||
;;
|
||||
2)
|
||||
apt install -y postgresql postgresql-contrib
|
||||
systemctl enable postgresql
|
||||
systemctl start postgresql
|
||||
echo "PostgreSQL 16 installed."
|
||||
echo ""
|
||||
echo "To create database:"
|
||||
echo " sudo -u postgres psql"
|
||||
echo " CREATE DATABASE your_app;"
|
||||
echo " CREATE USER your_user WITH ENCRYPTED PASSWORD 'password';"
|
||||
echo " GRANT ALL PRIVILEGES ON DATABASE your_app TO your_user;"
|
||||
;;
|
||||
3)
|
||||
echo "SQLite selected - no server installation needed."
|
||||
echo "SQLite is included with PHP (php8.3-sqlite3 already installed)."
|
||||
;;
|
||||
4)
|
||||
apt install -y mysql-server postgresql postgresql-contrib
|
||||
systemctl enable mysql postgresql
|
||||
systemctl start mysql postgresql
|
||||
echo "Both MySQL and PostgreSQL installed."
|
||||
;;
|
||||
esac
|
||||
|
||||
# Install Redis
|
||||
echo "[7/8] Installing Redis..."
|
||||
apt install -y redis-server
|
||||
systemctl enable redis-server
|
||||
systemctl start redis-server
|
||||
|
||||
# Web server selection
|
||||
echo "[8/8] Web Server Installation..."
|
||||
echo ""
|
||||
echo "Select web server to install:"
|
||||
echo "1) Nginx (recommended for Nginx Proxy Manager setup)"
|
||||
echo "2) Apache"
|
||||
echo "3) Both"
|
||||
echo "4) Skip (install manually later)"
|
||||
read -p "Enter choice [1-4]: " WEB_SERVER_CHOICE
|
||||
|
||||
case $WEB_SERVER_CHOICE in
|
||||
1)
|
||||
apt install -y nginx
|
||||
systemctl enable nginx
|
||||
systemctl start nginx
|
||||
echo "Nginx installed."
|
||||
;;
|
||||
2)
|
||||
apt install -y apache2 libapache2-mod-fcgid
|
||||
a2enmod rewrite headers ssl proxy_fcgi deflate expires setenvif
|
||||
systemctl enable apache2
|
||||
systemctl start apache2
|
||||
echo "Apache installed with required modules."
|
||||
;;
|
||||
3)
|
||||
apt install -y nginx apache2 libapache2-mod-fcgid
|
||||
a2enmod rewrite headers ssl proxy_fcgi deflate expires setenvif
|
||||
systemctl enable nginx apache2
|
||||
# Stop Apache by default to avoid port conflict
|
||||
systemctl stop apache2
|
||||
systemctl start nginx
|
||||
echo "Both installed. Nginx is running. Apache is stopped (start manually when needed)."
|
||||
;;
|
||||
4)
|
||||
echo "Skipping web server installation."
|
||||
;;
|
||||
esac
|
||||
|
||||
# Configure PHP-FPM
|
||||
echo ""
|
||||
echo "Configuring PHP-FPM..."
|
||||
cat > /etc/php/8.3/fpm/conf.d/99-laravel.ini << 'EOF'
|
||||
upload_max_filesize = 100M
|
||||
post_max_size = 100M
|
||||
max_execution_time = 300
|
||||
memory_limit = 512M
|
||||
opcache.enable = 1
|
||||
opcache.memory_consumption = 256
|
||||
opcache.interned_strings_buffer = 16
|
||||
opcache.max_accelerated_files = 10000
|
||||
opcache.validate_timestamps = 0
|
||||
EOF
|
||||
|
||||
systemctl restart php8.3-fpm
|
||||
|
||||
# Create web directory
|
||||
echo ""
|
||||
echo "Creating web directory structure..."
|
||||
mkdir -p /var/www
|
||||
chown -R www-data:www-data /var/www
|
||||
|
||||
# Setup firewall
|
||||
echo ""
|
||||
echo "Configuring UFW firewall..."
|
||||
ufw allow OpenSSH
|
||||
ufw allow 'Nginx Full' 2>/dev/null || true
|
||||
ufw allow 'Apache Full' 2>/dev/null || true
|
||||
ufw --force enable
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Server setup complete!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "Installed:"
|
||||
echo " - PHP 8.3 with FPM and extensions (MySQL, PostgreSQL, SQLite drivers)"
|
||||
echo " - Composer"
|
||||
echo " - Node.js 20.x"
|
||||
echo " - Database server (based on selection)"
|
||||
echo " - Redis"
|
||||
echo " - Web server (based on selection)"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo " 1. Create database and user for your selected database"
|
||||
echo " 2. Clone your Laravel app to /var/www/your-app"
|
||||
echo " 3. Copy appropriate .env file from deploy/production/"
|
||||
echo " - .env.mysql.production"
|
||||
echo " - .env.pgsql.production"
|
||||
echo " - .env.sqlite.production"
|
||||
echo " 4. Configure web server (use configs from deploy/nginx or deploy/apache)"
|
||||
echo " 5. Set permissions: deploy/scripts/fix-permissions.sh"
|
||||
echo ""
|
||||
14
deploy/scripts/supervisor-scheduler.conf
Normal file
14
deploy/scripts/supervisor-scheduler.conf
Normal file
@@ -0,0 +1,14 @@
|
||||
# Laravel Scheduler via Supervisor (alternative to cron)
|
||||
# Copy to: /etc/supervisor/conf.d/laravel-scheduler.conf
|
||||
# This runs the scheduler in a loop instead of using cron
|
||||
|
||||
[program:laravel-scheduler]
|
||||
process_name=%(program_name)s
|
||||
command=/bin/bash -c "while [ true ]; do php /var/www/your-app/artisan schedule:run --verbose --no-interaction >> /var/www/your-app/storage/logs/scheduler.log 2>&1; sleep 60; done"
|
||||
autostart=true
|
||||
autorestart=true
|
||||
user=www-data
|
||||
numprocs=1
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/var/www/your-app/storage/logs/supervisor-scheduler.log
|
||||
stopwaitsecs=60
|
||||
12
deploy/scripts/supervisor-worker.conf
Normal file
12
deploy/scripts/supervisor-worker.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
[program:laravel-worker]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php /var/www/your-app/artisan queue:work redis --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/your-app/storage/logs/worker.log
|
||||
stopwaitsecs=3600
|
||||
Reference in New Issue
Block a user