mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
Fix admin CSS not loading and quirks mode issues
Fixed multiple issues in admin panel: 1. CSS path: modern-normalize.css → modern-normalize.min.css (File is actually named .min.css) 2. Icon path: assets/icon.svg → /assets/admin_favicon.svg (Was relative, now absolute; correct filename) 3. Navigation: /admin/list.php → /admin/ (list.php was renamed to index.php) 4. Short PHP tags: <? → <?php (Better compatibility, some servers don't enable short_open_tag) 5. Quirks mode warning was due to CSS not loading, not DOCTYPE (DOCTYPE was already present) Files modified: - public/admin/inc/head.php (main fixes) - public/admin/index.php (short tags) - public/admin/add.php (short tags) - public/admin/import.php (short tags) Need to redeploy for production: just deploy
This commit is contained in:
400
docs/COMPLETE_DEPLOYMENT_GUIDE.md
Normal file
400
docs/COMPLETE_DEPLOYMENT_GUIDE.md
Normal file
@@ -0,0 +1,400 @@
|
||||
# Complete Deployment Guide - New Structure
|
||||
|
||||
## Overview
|
||||
|
||||
This guide walks you through deploying the new secure directory structure:
|
||||
- **Old:** `/var/www/html/` (everything exposed)
|
||||
- **New:** `/var/www/posterg/` with `public/` subdirectory (only public/ exposed)
|
||||
|
||||
## Step-by-Step Deployment
|
||||
|
||||
### ⚠️ IMPORTANT: Do NOT delete /var/www/html/ yet!
|
||||
|
||||
Keep it as a backup until you confirm the new structure works.
|
||||
|
||||
---
|
||||
|
||||
### Step 1: Setup Server Directory (Manual - One Time)
|
||||
|
||||
SSH to server and create the new directory:
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
|
||||
# Backup current site
|
||||
sudo cp -r /var/www/html /var/www/html.backup
|
||||
|
||||
# Create new directory
|
||||
sudo mkdir -p /var/www/posterg
|
||||
|
||||
# Set ownership (www-data = web server user)
|
||||
sudo chown www-data:posterg /var/www/posterg
|
||||
|
||||
# Set permissions
|
||||
sudo chmod 775 /var/www/posterg
|
||||
|
||||
# Verify
|
||||
ls -ld /var/www/posterg
|
||||
# Should show: drwxrwxr-x 2 www-data posterg ...
|
||||
|
||||
# Exit server
|
||||
exit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Deploy Application Files
|
||||
|
||||
From your local machine:
|
||||
|
||||
```bash
|
||||
just deploy
|
||||
```
|
||||
|
||||
This will:
|
||||
- Upload all files to `/var/www/posterg/`
|
||||
- Exclude unnecessary files (tests, docs, etc.)
|
||||
- Set initial ownership to `www-data:posterg`
|
||||
|
||||
You should see:
|
||||
```
|
||||
sending incremental file list
|
||||
public/index.php
|
||||
public/search.php
|
||||
public/memoire.php
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Deploy Nginx Configuration
|
||||
|
||||
```bash
|
||||
just deploy-nginx
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Check that nginx config has correct DocumentRoot (`/var/www/posterg/public`)
|
||||
2. Upload `posterg.conf` to `/tmp/` on server
|
||||
3. Upload `deploy-production-new.sh` to `/tmp/` on server
|
||||
|
||||
Expected output:
|
||||
```
|
||||
✅ nginx config looks correct
|
||||
✅ Files uploaded to /tmp/ on server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 4: Apply Nginx Configuration on Server
|
||||
|
||||
SSH to server and run the deployment script:
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo bash /tmp/deploy-production.sh
|
||||
```
|
||||
|
||||
The script will:
|
||||
1. Fix file permissions on `/var/www/posterg/`
|
||||
2. Backup existing nginx config
|
||||
3. Install new nginx config
|
||||
4. Test nginx configuration
|
||||
5. Show you the reload command
|
||||
|
||||
Expected output:
|
||||
```
|
||||
🚀 Post-ERG Production Deployment (NEW STRUCTURE)
|
||||
==================================================
|
||||
|
||||
📋 Step 1: Fixing file permissions...
|
||||
✓ Changed ownership to www-data:posterg
|
||||
✓ Set directory permissions to 755
|
||||
✓ Set file permissions to 644
|
||||
✓ Made database directory group-writable (775)
|
||||
✓ Fixed database file permissions (660)
|
||||
|
||||
📋 Step 2: Deploying nginx configuration...
|
||||
✓ Backed up existing config
|
||||
✓ Installed new nginx config
|
||||
|
||||
📋 Step 3: Testing nginx configuration...
|
||||
✓ Nginx configuration is valid
|
||||
|
||||
📋 Step 4: Summary...
|
||||
✓ Permissions fixed
|
||||
✓ Nginx config installed
|
||||
✓ Configuration validated
|
||||
|
||||
Ready to reload nginx!
|
||||
|
||||
Run: sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 5: Reload Nginx
|
||||
|
||||
Still on the server:
|
||||
|
||||
```bash
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
If successful, you'll see no output (which is good!).
|
||||
|
||||
Check status:
|
||||
```bash
|
||||
sudo systemctl status nginx
|
||||
# Should show "active (running)"
|
||||
```
|
||||
|
||||
Exit server:
|
||||
```bash
|
||||
exit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 6: Verify Deployment
|
||||
|
||||
From your local machine:
|
||||
|
||||
```bash
|
||||
just server-status
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
🔍 Server Status
|
||||
================
|
||||
✓ Nginx running
|
||||
✓ PHP-FPM running
|
||||
|
||||
Site check:
|
||||
• Public: 200 ✓
|
||||
• Admin: 200 ✓
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 7: Security Verification
|
||||
|
||||
Test these URLs in your browser or with curl:
|
||||
|
||||
```bash
|
||||
# Should work (200 OK):
|
||||
curl -I https://posterg.erg.be/
|
||||
curl -I https://posterg.erg.be/admin/
|
||||
|
||||
# Should be 404 (SECURITY - private files):
|
||||
curl -I https://posterg.erg.be/database/test.db
|
||||
curl -I https://posterg.erg.be/config/bootstrap.php
|
||||
curl -I https://posterg.erg.be/includes/header.php
|
||||
curl -I https://posterg.erg.be/lib/Database.php
|
||||
```
|
||||
|
||||
**All private files must return 404!** If they don't, nginx is not configured correctly.
|
||||
|
||||
---
|
||||
|
||||
### Step 8: Deploy Database (If Needed)
|
||||
|
||||
If you need to update the database:
|
||||
|
||||
```bash
|
||||
just deploy-database
|
||||
```
|
||||
|
||||
This will warn you before overwriting.
|
||||
|
||||
---
|
||||
|
||||
### Step 9: Test Thoroughly
|
||||
|
||||
- [ ] Visit https://posterg.erg.be/
|
||||
- [ ] Browse thesis list
|
||||
- [ ] Open a thesis detail page
|
||||
- [ ] Try search functionality
|
||||
- [ ] Access admin panel (should require login)
|
||||
- [ ] Verify private files return 404
|
||||
|
||||
---
|
||||
|
||||
### Step 10: Keep Backup for a While
|
||||
|
||||
**Do NOT delete `/var/www/html/` immediately!**
|
||||
|
||||
Keep it for a few days to ensure everything works. If you need to rollback:
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo nano /etc/nginx/sites-available/posterg
|
||||
# Change: root /var/www/posterg/public;
|
||||
# Back to: root /var/www/html;
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
Your old site will work immediately.
|
||||
|
||||
---
|
||||
|
||||
## After Confirming Everything Works
|
||||
|
||||
A few days later, once you're confident:
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo rm -rf /var/www/html.backup
|
||||
sudo rm -rf /var/www/html
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What Changed?
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
OLD: NEW:
|
||||
/var/www/html/ /var/www/posterg/
|
||||
├── index.php ├── public/ ← DocumentRoot
|
||||
├── search.php │ ├── index.php
|
||||
├── admin/ │ ├── search.php
|
||||
├── assets/ │ ├── memoire.php
|
||||
├── database/ ❌ exposed │ ├── admin/
|
||||
├── lib/ ❌ exposed │ └── assets/
|
||||
└── ... ├── includes/ ✅ private
|
||||
├── config/ ✅ private
|
||||
├── database/ ✅ private
|
||||
└── lib/ ✅ private
|
||||
```
|
||||
|
||||
### Nginx Configuration
|
||||
|
||||
```nginx
|
||||
# OLD
|
||||
root /var/www/html;
|
||||
location ^~ /formulaire/ { ... }
|
||||
|
||||
# NEW
|
||||
root /var/www/posterg/public;
|
||||
location ^~ /admin/ { ... }
|
||||
```
|
||||
|
||||
### Security Impact
|
||||
|
||||
| Resource | Old | New |
|
||||
|----------|-----|-----|
|
||||
| Database | ❌ Accessible if nginx misconfigured | ✅ Physically outside web root |
|
||||
| Config files | ❌ One deny rule away | ✅ Physically private |
|
||||
| Source code | ❌ Exposed | ✅ Physically private |
|
||||
| Admin panel | /formulaire/ | /admin/ |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Site returns 404 for everything
|
||||
|
||||
**Cause:** Nginx still pointing to old location or wrong DocumentRoot
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo cat /etc/nginx/sites-available/posterg | grep "root "
|
||||
# Should show: root /var/www/posterg/public;
|
||||
```
|
||||
|
||||
If wrong:
|
||||
```bash
|
||||
sudo nano /etc/nginx/sites-available/posterg
|
||||
# Fix the root directive
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Database errors
|
||||
|
||||
**Cause:** Wrong permissions on database file
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo chown www-data:posterg /var/www/posterg/database/test.db
|
||||
sudo chmod 660 /var/www/posterg/database/test.db
|
||||
```
|
||||
|
||||
### Admin upload errors
|
||||
|
||||
**Cause:** Upload directories not writable
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo chmod 775 /var/www/posterg/public/admin/data
|
||||
sudo find /var/www/posterg/public/admin/data -type d -exec chmod 775 {} \;
|
||||
```
|
||||
|
||||
### Private files still accessible
|
||||
|
||||
**Cause:** Nginx serving from wrong directory
|
||||
|
||||
**Fix:** Verify nginx DocumentRoot and reload
|
||||
|
||||
---
|
||||
|
||||
## Rollback Procedure
|
||||
|
||||
If you need to go back to the old structure:
|
||||
|
||||
```bash
|
||||
# 1. SSH to server
|
||||
ssh posterg
|
||||
|
||||
# 2. Restore old nginx config
|
||||
sudo nano /etc/nginx/sites-available/posterg
|
||||
# Change: root /var/www/posterg/public;
|
||||
# To: root /var/www/html;
|
||||
# Change: location ^~ /admin/
|
||||
# To: location ^~ /formulaire/
|
||||
|
||||
# 3. Reload nginx
|
||||
sudo systemctl reload nginx
|
||||
|
||||
# 4. Verify
|
||||
curl -I https://posterg.erg.be/
|
||||
```
|
||||
|
||||
Your old site should work immediately (as long as you didn't delete `/var/www/html/`).
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Task | Command |
|
||||
|------|---------|
|
||||
| Deploy files | `just deploy` |
|
||||
| Deploy nginx | `just deploy-nginx` |
|
||||
| Deploy database | `just deploy-database` |
|
||||
| Check status | `just server-status` |
|
||||
| View logs | `just server-logs` |
|
||||
|
||||
---
|
||||
|
||||
## Success Checklist
|
||||
|
||||
- [ ] `/var/www/posterg/` created with correct permissions
|
||||
- [ ] Files deployed with `just deploy`
|
||||
- [ ] Nginx config deployed with `just deploy-nginx`
|
||||
- [ ] Permissions fixed with `deploy-production.sh`
|
||||
- [ ] Nginx reloaded successfully
|
||||
- [ ] Site accessible at https://posterg.erg.be/
|
||||
- [ ] Admin accessible at https://posterg.erg.be/admin/
|
||||
- [ ] Private files return 404 (security verified)
|
||||
- [ ] Database working (can view theses)
|
||||
- [ ] Search working
|
||||
- [ ] Old `/var/www/html/` kept as backup
|
||||
|
||||
---
|
||||
|
||||
**After deployment, your site will be significantly more secure!** 🔒
|
||||
571
docs/DEPLOYMENT_MIGRATION.md
Normal file
571
docs/DEPLOYMENT_MIGRATION.md
Normal file
@@ -0,0 +1,571 @@
|
||||
# Deployment & Dev Server Migration Guide
|
||||
|
||||
Analysis of current `justfile` and required changes for the new directory structure.
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Current Setup Analysis
|
||||
|
||||
### Current Dev Server (❌ INCORRECT)
|
||||
```bash
|
||||
# From justfile line 33
|
||||
php -S 127.0.0.1:8000
|
||||
```
|
||||
|
||||
**Problems:**
|
||||
- Serves from project root (all files accessible via web)
|
||||
- Exposes sensitive files: `database/`, `tests/`, `vendor/`, config files
|
||||
- Doesn't match production DocumentRoot configuration
|
||||
- Security risk: `.env`, database files, source code all accessible
|
||||
|
||||
### Current Deployment (❌ INCORRECT)
|
||||
```bash
|
||||
# From justfile lines 56-75
|
||||
rsync -vur --progress \
|
||||
--exclude 'vendor' --exclude 'tests' --exclude '*.db' ... \
|
||||
./ posterg:/var/www/html/
|
||||
```
|
||||
|
||||
**Problems:**
|
||||
- Deploys entire project to DocumentRoot
|
||||
- Relies on exclusions to hide sensitive files (error-prone)
|
||||
- Wrong structure: `/var/www/html/` should only contain public files
|
||||
- Private files (`src/`, `config/`) are still in DocumentRoot
|
||||
- Nginx serves from `/var/www/html/` exposing everything not excluded
|
||||
|
||||
---
|
||||
|
||||
## ✅ Required Changes
|
||||
|
||||
### 1. New Directory Structure on Server
|
||||
|
||||
**Before (current):**
|
||||
```
|
||||
/var/www/html/ # DocumentRoot ❌
|
||||
├── index.php # Public
|
||||
├── search.php # Public
|
||||
├── admin/ # Public (protected by nginx)
|
||||
├── assets/ # Public
|
||||
├── inc/ # ❌ EXPOSED (config files!)
|
||||
├── lib/ # ❌ EXPOSED (source code!)
|
||||
├── database/ # ❌ EXPOSED (database files!)
|
||||
└── vendor/ # ❌ (excluded but in wrong place)
|
||||
```
|
||||
|
||||
**After (recommended):**
|
||||
```
|
||||
/var/www/posterg/ # Application root (private)
|
||||
├── public/ # DocumentRoot ✅ (only this exposed)
|
||||
│ ├── index.php
|
||||
│ ├── search.php
|
||||
│ ├── memoire.php
|
||||
│ ├── admin/
|
||||
│ └── assets/
|
||||
├── src/ # ✅ PRIVATE
|
||||
├── config/ # ✅ PRIVATE
|
||||
├── database/ # ✅ PRIVATE
|
||||
├── vendor/ # ✅ PRIVATE
|
||||
├── var/ # ✅ PRIVATE (cache, logs)
|
||||
└── lib/ # ✅ PRIVATE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Updated Justfile
|
||||
|
||||
### Change 1: Dev Server
|
||||
|
||||
**Current:**
|
||||
```just
|
||||
[group('dev')]
|
||||
serve:
|
||||
@echo "🚀 Starting Post-ERG development server"
|
||||
@echo "📍 Public site: http://localhost:8000"
|
||||
@echo "📍 Admin panel: http://localhost:8000/admin/"
|
||||
@php -S 127.0.0.1:8000
|
||||
```
|
||||
|
||||
**New:**
|
||||
```just
|
||||
[group('dev')]
|
||||
serve:
|
||||
@echo "🚀 Starting Post-ERG development server"
|
||||
@echo "========================================"
|
||||
@echo ""
|
||||
@echo "📍 Public site: http://localhost:8000"
|
||||
@echo "📍 Admin panel: http://localhost:8000/admin/"
|
||||
@echo ""
|
||||
@echo "🔒 Serving from public/ directory (matches production)"
|
||||
@echo ""
|
||||
@if [ -d "vendor/php-live-reload" ]; then \
|
||||
echo "✨ Live reload enabled - browser auto-refreshes on file save!"; \
|
||||
else \
|
||||
echo "💡 Tip: Run 'just setup' to enable live reload"; \
|
||||
fi
|
||||
@echo ""
|
||||
@echo "Press Ctrl+C to stop"
|
||||
@echo ""
|
||||
@php -S 127.0.0.1:8000 -t public/
|
||||
|
||||
# Alternative: If you need router script for URL rewriting
|
||||
[group('dev')]
|
||||
serve-router:
|
||||
@echo "🚀 Starting with router script (for clean URLs)"
|
||||
@php -S 127.0.0.1:8000 -t public/ public/router.php
|
||||
```
|
||||
|
||||
**Key change:** `-t public/` flag tells PHP server to use `public/` as DocumentRoot
|
||||
|
||||
---
|
||||
|
||||
### Change 2: Deployment Strategy
|
||||
|
||||
**Current (❌):**
|
||||
```just
|
||||
deploy:
|
||||
rsync -vur --progress \
|
||||
--exclude 'vendor' --exclude 'tests' ... \
|
||||
./ posterg:/var/www/html/
|
||||
```
|
||||
|
||||
**New (✅) - Two-Step Deployment:**
|
||||
|
||||
```just
|
||||
[group('deploy')]
|
||||
deploy:
|
||||
@echo "📤 Deploying Post-ERG site"
|
||||
@echo "=========================="
|
||||
@echo ""
|
||||
@echo "Step 1: Deploying application files..."
|
||||
|
||||
# Deploy entire application to private directory
|
||||
rsync -vur --progress \
|
||||
--exclude '.git*' \
|
||||
--exclude '.jj' \
|
||||
--exclude 'tests/' \
|
||||
--exclude 'docs/' \
|
||||
--exclude '*.md' \
|
||||
--exclude 'justfile*' \
|
||||
--exclude 'setup-dev.sh' \
|
||||
--exclude 'migrate-structure.sh' \
|
||||
--exclude 'database/test.db' \
|
||||
--exclude 'database/backup_*' \
|
||||
--exclude 'database/fixtures/' \
|
||||
--exclude 'var/cache/*' \
|
||||
--exclude 'var/logs/*' \
|
||||
--exclude '.DS_Store' \
|
||||
./ posterg:/var/www/posterg/
|
||||
|
||||
@echo ""
|
||||
@echo "Step 2: Setting up directory structure..."
|
||||
|
||||
# Create necessary directories on server
|
||||
ssh posterg "mkdir -p /var/www/posterg/var/{cache,logs,tmp} && \
|
||||
chown -R www-data:posterg /var/www/posterg/var && \
|
||||
chmod -R 775 /var/www/posterg/var"
|
||||
|
||||
@echo ""
|
||||
@echo "Step 3: Setting permissions..."
|
||||
|
||||
# Set correct ownership and permissions
|
||||
ssh posterg "cd /var/www/posterg && \
|
||||
chown -R www-data:posterg . && \
|
||||
find . -type d -exec chmod 755 {} \; && \
|
||||
find . -type f -exec chmod 644 {} \; && \
|
||||
chmod -R 775 var/ && \
|
||||
chmod -R 775 database/ && \
|
||||
chmod 660 database/*.db"
|
||||
|
||||
@echo ""
|
||||
@echo "✅ Deployment complete!"
|
||||
@echo ""
|
||||
@echo "🔍 Verify deployment:"
|
||||
@echo " • Public: https://posterg.erg.be/"
|
||||
@echo " • Admin: https://posterg.erg.be/admin/"
|
||||
@echo ""
|
||||
@echo "📁 Server structure:"
|
||||
@echo " • App root: /var/www/posterg/"
|
||||
@echo " • DocumentRoot: /var/www/posterg/public/"
|
||||
|
||||
# Quick deploy - only public files (faster for frontend changes)
|
||||
[group('deploy')]
|
||||
deploy-public:
|
||||
@echo "⚡ Quick deploy: public files only"
|
||||
rsync -vur --progress \
|
||||
--delete \
|
||||
./public/ posterg:/var/www/posterg/public/
|
||||
@echo "✅ Public files updated"
|
||||
|
||||
# Deploy only code (no assets)
|
||||
[group('deploy')]
|
||||
deploy-code:
|
||||
@echo "⚡ Deploying PHP code only"
|
||||
rsync -vur --progress \
|
||||
--include='**.php' \
|
||||
--include='**/' \
|
||||
--exclude='*' \
|
||||
./ posterg:/var/www/posterg/
|
||||
@echo "✅ Code updated"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Change 3: Database Deployment
|
||||
|
||||
**Current:**
|
||||
```just
|
||||
test-deploy:
|
||||
ssh posterg "mkdir -p /var/www/html/database"
|
||||
rsync -vur --progress ./database/test.db posterg:/var/www/html/database/test.db
|
||||
```
|
||||
|
||||
**New:**
|
||||
```just
|
||||
[group('deploy')]
|
||||
deploy-database:
|
||||
@echo "📊 Deploying database..."
|
||||
@echo "⚠️ This will overwrite the remote database!"
|
||||
@read -p "Continue? [y/N] " -n 1 -r; \
|
||||
echo; \
|
||||
if [[ $$REPLY =~ ^[Yy]$$ ]]; then \
|
||||
ssh posterg "mkdir -p /var/www/posterg/database" && \
|
||||
rsync -vur --progress ./database/test.db posterg:/var/www/posterg/database/ && \
|
||||
ssh posterg "chown www-data:posterg /var/www/posterg/database/test.db && \
|
||||
chmod 660 /var/www/posterg/database/test.db" && \
|
||||
echo "✅ Database deployed"; \
|
||||
else \
|
||||
echo "❌ Cancelled"; \
|
||||
fi
|
||||
|
||||
# Backup remote database before deploying
|
||||
[group('deploy')]
|
||||
backup-remote-db:
|
||||
@echo "💾 Backing up remote database..."
|
||||
@ssh posterg "sqlite3 /var/www/posterg/database/test.db .dump" > database/remote_backup_$(date +%Y%m%d_%H%M%S).sql
|
||||
@echo "✅ Remote database backed up locally"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Change 4: Updated Nginx Deployment
|
||||
|
||||
**Current nginx configuration probably points to:**
|
||||
```nginx
|
||||
root /var/www/html;
|
||||
```
|
||||
|
||||
**Should change to:**
|
||||
```nginx
|
||||
root /var/www/posterg/public;
|
||||
```
|
||||
|
||||
**Updated recipe:**
|
||||
```just
|
||||
[group('server')]
|
||||
deploy-nginx:
|
||||
@echo "🔧 Deploying nginx configuration..."
|
||||
@echo ""
|
||||
@echo "⚠️ IMPORTANT: Nginx config must point to /var/www/posterg/public"
|
||||
@echo ""
|
||||
|
||||
# Check if nginx config has correct DocumentRoot
|
||||
@if ! grep -q "/var/www/posterg/public" nginx/posterg.conf 2>/dev/null; then \
|
||||
echo "❌ ERROR: nginx/posterg.conf doesn't contain '/var/www/posterg/public'"; \
|
||||
echo " Update DocumentRoot before deploying!"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
rsync -vur --progress ./nginx/posterg.conf posterg:/tmp/posterg.conf
|
||||
rsync -vur --progress ./nginx/deploy-production.sh posterg:/tmp/deploy-production.sh
|
||||
|
||||
@echo "✅ Files uploaded to /tmp/ on server"
|
||||
@echo ""
|
||||
@echo "Next steps on the server:"
|
||||
@echo " ssh posterg"
|
||||
@echo " sudo bash /tmp/deploy-production.sh"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Nginx Configuration Changes
|
||||
|
||||
### Update `nginx/posterg.conf`
|
||||
|
||||
**Find and replace:**
|
||||
```nginx
|
||||
# OLD
|
||||
root /var/www/html;
|
||||
|
||||
# NEW
|
||||
root /var/www/posterg/public;
|
||||
```
|
||||
|
||||
**Complete example:**
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name posterg.erg.be;
|
||||
|
||||
# Redirect to HTTPS
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name posterg.erg.be;
|
||||
|
||||
# NEW DocumentRoot - only public directory
|
||||
root /var/www/posterg/public;
|
||||
index index.php index.html;
|
||||
|
||||
# SSL configuration
|
||||
ssl_certificate /etc/letsencrypt/live/posterg.erg.be/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/posterg.erg.be/privkey.pem;
|
||||
|
||||
# Logs
|
||||
access_log /var/log/nginx/posterg_access.log;
|
||||
error_log /var/log/nginx/posterg_error.log;
|
||||
|
||||
# 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;
|
||||
|
||||
# Deny access to sensitive files (should already be outside public/)
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~ /database/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Admin area - basic auth
|
||||
location /admin/ {
|
||||
auth_basic "Admin Access";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
|
||||
# IMPORTANT: Set correct SCRIPT_FILENAME
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
}
|
||||
}
|
||||
|
||||
# PHP files
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
}
|
||||
|
||||
# Static files
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# Deny access to uploaded files execution
|
||||
location ~ ^/uploads/.*\.php$ {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Migration Steps
|
||||
|
||||
### Step 1: Local Development
|
||||
```bash
|
||||
# 1. Create new structure
|
||||
mkdir -p public/{admin,assets}
|
||||
mkdir -p src config var/{cache,logs,tmp}
|
||||
|
||||
# 2. Move public files
|
||||
mv index.php search.php memoire.php public/
|
||||
mv assets/* public/assets/
|
||||
mv admin/* public/admin/
|
||||
|
||||
# 3. Move private files
|
||||
mv inc/* config/ # or src/ depending on content
|
||||
mv lib src/lib
|
||||
|
||||
# 4. Update paths in PHP files (see PATHS_UPDATE.md below)
|
||||
|
||||
# 5. Test local dev server
|
||||
just serve
|
||||
# Opens http://localhost:8000
|
||||
# Verify that sensitive files return 404:
|
||||
# http://localhost:8000/database/test.db → 404
|
||||
# http://localhost:8000/config/ → 404
|
||||
# http://localhost:8000/src/ → 404
|
||||
```
|
||||
|
||||
### Step 2: Update Nginx Config
|
||||
```bash
|
||||
# Edit nginx/posterg.conf
|
||||
# Change: root /var/www/html;
|
||||
# To: root /var/www/posterg/public;
|
||||
|
||||
# Validate locally
|
||||
nginx -t -c nginx/posterg.conf
|
||||
```
|
||||
|
||||
### Step 3: Deploy
|
||||
```bash
|
||||
# 1. Backup current production
|
||||
ssh posterg "tar -czf /tmp/posterg-backup-$(date +%Y%m%d).tar.gz /var/www/html"
|
||||
|
||||
# 2. Create new directory structure
|
||||
ssh posterg "mkdir -p /var/www/posterg"
|
||||
|
||||
# 3. Deploy application
|
||||
just deploy
|
||||
|
||||
# 4. Deploy nginx config
|
||||
just deploy-nginx
|
||||
|
||||
# 5. On server: activate new config
|
||||
ssh posterg
|
||||
sudo bash /tmp/deploy-production.sh
|
||||
|
||||
# 6. Reload nginx
|
||||
sudo systemctl reload nginx
|
||||
|
||||
# 7. Test
|
||||
just server-status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Checklist
|
||||
|
||||
### Local Testing
|
||||
- [ ] `just serve` starts on port 8000
|
||||
- [ ] Public site loads: http://localhost:8000
|
||||
- [ ] Admin loads: http://localhost:8000/admin/
|
||||
- [ ] Assets load (CSS, images, JS)
|
||||
- [ ] Database files NOT accessible via browser
|
||||
- [ ] Config files NOT accessible via browser
|
||||
- [ ] Tests still pass: `just test`
|
||||
|
||||
### Production Testing
|
||||
- [ ] HTTPS works: https://posterg.erg.be/
|
||||
- [ ] Admin login works
|
||||
- [ ] Search functionality works
|
||||
- [ ] Database connections work
|
||||
- [ ] File uploads work (if applicable)
|
||||
- [ ] Logs written to `/var/www/posterg/var/logs/`
|
||||
- [ ] Sensitive URLs return 404:
|
||||
- https://posterg.erg.be/database/test.db
|
||||
- https://posterg.erg.be/config/
|
||||
- https://posterg.erg.be/src/
|
||||
- https://posterg.erg.be/vendor/
|
||||
|
||||
---
|
||||
|
||||
## 📊 Path Changes Summary
|
||||
|
||||
| File Type | Current Path | New Path |
|
||||
|-----------|-------------|----------|
|
||||
| Public index | `/index.php` | `/public/index.php` |
|
||||
| Admin panel | `/admin/` | `/public/admin/` |
|
||||
| Assets | `/assets/` | `/public/assets/` |
|
||||
| Config | `/inc/` | `/config/` or `/src/` |
|
||||
| Libraries | `/lib/` | `/src/lib/` |
|
||||
| Database | `/database/` | `/database/` (stays) |
|
||||
| Vendor | `/vendor/` | `/vendor/` (stays) |
|
||||
| Tests | `/tests/` | `/tests/` (stays) |
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security Improvements
|
||||
|
||||
### Before
|
||||
- ❌ All files in DocumentRoot
|
||||
- ❌ Relies on nginx deny rules
|
||||
- ❌ One misconfiguration = full exposure
|
||||
- ❌ Database accessible if nginx fails
|
||||
|
||||
### After
|
||||
- ✅ Only `public/` in DocumentRoot
|
||||
- ✅ Physical separation of public/private
|
||||
- ✅ Nginx misconfiguration = site down (not exposed)
|
||||
- ✅ Database physically unreachable via web
|
||||
|
||||
---
|
||||
|
||||
## 💡 Tips
|
||||
|
||||
### Router Script (for clean URLs)
|
||||
Create `public/router.php` for development:
|
||||
```php
|
||||
<?php
|
||||
// Development router script
|
||||
if (php_sapi_name() === 'cli-server') {
|
||||
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
|
||||
// Serve static files directly
|
||||
if (file_exists(__DIR__ . $path) && is_file(__DIR__ . $path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Route everything else to index.php
|
||||
require __DIR__ . '/index.php';
|
||||
}
|
||||
```
|
||||
|
||||
### Environment Detection
|
||||
In your code, detect environment:
|
||||
```php
|
||||
<?php
|
||||
// config/bootstrap.php
|
||||
define('IS_DEV', php_sapi_name() === 'cli-server');
|
||||
define('APP_ROOT', dirname(__DIR__)); // /var/www/posterg
|
||||
define('PUBLIC_ROOT', APP_ROOT . '/public');
|
||||
```
|
||||
|
||||
### Use Relative Requires
|
||||
```php
|
||||
// Before (brittle)
|
||||
require_once '/var/www/html/inc/config.php';
|
||||
|
||||
// After (portable)
|
||||
require_once __DIR__ . '/../config/app.php';
|
||||
// or
|
||||
require_once APP_ROOT . '/config/app.php';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Troubleshooting
|
||||
|
||||
### Issue: 404 on all pages after deploy
|
||||
**Cause:** Nginx DocumentRoot not updated
|
||||
**Fix:** Check nginx config has `root /var/www/posterg/public;`
|
||||
|
||||
### Issue: PHP includes fail
|
||||
**Cause:** Hardcoded paths or wrong APP_ROOT
|
||||
**Fix:** Use `__DIR__` or define APP_ROOT constant
|
||||
|
||||
### Issue: Database connection fails
|
||||
**Cause:** Path to database file wrong
|
||||
**Fix:** Update path from `database/test.db` to `../database/test.db` (from public/)
|
||||
|
||||
### Issue: Can't write to cache/logs
|
||||
**Cause:** Wrong permissions on var/ directory
|
||||
**Fix:** `sudo chown -R www-data:posterg /var/www/posterg/var && chmod -R 775 /var/www/posterg/var`
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Create `PATHS_UPDATE.md` - document all PHP file path changes needed
|
||||
2. Create `public/router.php` - for cleaner dev URLs
|
||||
3. Update all `require`/`include` statements to use relative paths
|
||||
4. Test migration on staging/local first
|
||||
5. Schedule production deployment during low-traffic period
|
||||
215
docs/DEPLOYMENT_STEPS.md
Normal file
215
docs/DEPLOYMENT_STEPS.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# Deployment Steps
|
||||
|
||||
## First-Time Deployment (New Structure)
|
||||
|
||||
Since we're moving from `/var/www/html/` to `/var/www/posterg/`, follow these steps:
|
||||
|
||||
### 1. Setup Server Directory (ONE TIME)
|
||||
|
||||
```bash
|
||||
just setup-server
|
||||
```
|
||||
|
||||
This creates `/var/www/posterg/` with correct permissions:
|
||||
- Owner: `www-data:posterg`
|
||||
- Permissions: `775`
|
||||
|
||||
### 2. Deploy Application
|
||||
|
||||
```bash
|
||||
just deploy
|
||||
```
|
||||
|
||||
This deploys all files to `/var/www/posterg/`:
|
||||
- `public/` → `/var/www/posterg/public/`
|
||||
- `includes/` → `/var/www/posterg/includes/`
|
||||
- `config/` → `/var/www/posterg/config/`
|
||||
- `database/` → `/var/www/posterg/database/`
|
||||
- `lib/` → `/var/www/posterg/lib/`
|
||||
|
||||
### 3. Update Nginx Configuration
|
||||
|
||||
```bash
|
||||
just deploy-nginx
|
||||
```
|
||||
|
||||
This checks that nginx config has correct DocumentRoot and uploads it to server.
|
||||
|
||||
**IMPORTANT:** The nginx config must have:
|
||||
```nginx
|
||||
root /var/www/posterg/public;
|
||||
```
|
||||
|
||||
If the check fails, edit `nginx/posterg.conf` first.
|
||||
|
||||
### 4. Apply Nginx Configuration on Server
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo bash /tmp/deploy-production.sh
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### 5. Verify Deployment
|
||||
|
||||
```bash
|
||||
just server-status
|
||||
```
|
||||
|
||||
Check:
|
||||
- https://posterg.erg.be/ (should work)
|
||||
- https://posterg.erg.be/admin/ (should work)
|
||||
- https://posterg.erg.be/database/test.db (should 404 ✅)
|
||||
|
||||
---
|
||||
|
||||
## Subsequent Deployments
|
||||
|
||||
After the first deployment, you only need:
|
||||
|
||||
```bash
|
||||
just deploy
|
||||
```
|
||||
|
||||
That's it! The directory structure is already in place.
|
||||
|
||||
---
|
||||
|
||||
## Deploy Database
|
||||
|
||||
If you need to deploy the database:
|
||||
|
||||
```bash
|
||||
just deploy-database
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Upload `database/test.db` to server
|
||||
2. Set correct permissions
|
||||
3. Warn before overwriting
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Permission Denied on Deploy
|
||||
|
||||
**Error:**
|
||||
```
|
||||
mkdir "/var/www/posterg" failed: Permission denied (13)
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
just setup-server
|
||||
```
|
||||
|
||||
### Nginx 500 Error
|
||||
|
||||
**Cause:** Nginx DocumentRoot still pointing to old location
|
||||
|
||||
**Solution:**
|
||||
1. Check nginx config has: `root /var/www/posterg/public;`
|
||||
2. Redeploy nginx config:
|
||||
```bash
|
||||
just deploy-nginx
|
||||
ssh posterg
|
||||
sudo bash /tmp/deploy-production.sh
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Database Connection Errors
|
||||
|
||||
**Cause:** Database file permissions incorrect
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
ssh posterg
|
||||
cd /var/www/posterg
|
||||
sudo chown www-data:posterg database/test.db
|
||||
sudo chmod 660 database/test.db
|
||||
```
|
||||
|
||||
### Admin 404
|
||||
|
||||
**Cause:** Nginx still using old `/formulaire/` location
|
||||
|
||||
**Solution:** Update `nginx/posterg.conf` to use `/admin/` location
|
||||
|
||||
---
|
||||
|
||||
## Rollback
|
||||
|
||||
If something goes wrong, rollback is easy:
|
||||
|
||||
### 1. Restore Old Directory
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo cp -r /var/www/html.backup /var/www/html # If you backed up
|
||||
```
|
||||
|
||||
### 2. Restore Old Nginx Config
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo cp /etc/nginx/sites-available/posterg.backup /etc/nginx/sites-available/posterg
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### 3. Rollback Code with jj
|
||||
|
||||
```bash
|
||||
jj log
|
||||
jj edit <previous-change-id>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration Checklist
|
||||
|
||||
- [ ] `just setup-server` - Create server directory
|
||||
- [ ] `just deploy` - Deploy application
|
||||
- [ ] `just deploy-nginx` - Update nginx config
|
||||
- [ ] SSH to server and apply nginx config
|
||||
- [ ] `sudo systemctl reload nginx`
|
||||
- [ ] Verify site works: https://posterg.erg.be/
|
||||
- [ ] Verify security: https://posterg.erg.be/database/test.db → 404
|
||||
- [ ] Test admin: https://posterg.erg.be/admin/
|
||||
- [ ] Deploy database (if needed): `just deploy-database`
|
||||
|
||||
---
|
||||
|
||||
## Commands Reference
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `just setup-server` | Create `/var/www/posterg/` (first time only) |
|
||||
| `just deploy` | Deploy application files |
|
||||
| `just deploy-nginx` | Update nginx configuration |
|
||||
| `just deploy-database` | Deploy database file |
|
||||
| `just server-status` | Check server health |
|
||||
| `just server-logs` | View server logs |
|
||||
|
||||
---
|
||||
|
||||
## Directory Structure on Server
|
||||
|
||||
```
|
||||
/var/www/posterg/ # Application root (private)
|
||||
├── public/ # DocumentRoot (nginx points here)
|
||||
│ ├── index.php
|
||||
│ ├── search.php
|
||||
│ ├── memoire.php
|
||||
│ ├── admin/
|
||||
│ └── assets/
|
||||
├── includes/ # Templates (private)
|
||||
├── config/ # Configuration (private)
|
||||
├── database/ # Database (private)
|
||||
├── lib/ # PHP classes (private)
|
||||
└── vendor/ # Dependencies (private)
|
||||
```
|
||||
|
||||
**Nginx DocumentRoot:** `/var/www/posterg/public/`
|
||||
|
||||
Only the `public/` directory is accessible via web browser. Everything else is private.
|
||||
246
docs/DIRECTORY_STRUCTURE.md
Normal file
246
docs/DIRECTORY_STRUCTURE.md
Normal file
@@ -0,0 +1,246 @@
|
||||
# Recommended Directory Structure
|
||||
|
||||
Based on the **Standard PHP Package Skeleton** (researched by Paul M. Jones from thousands of GitHub projects).
|
||||
|
||||
## Directory Layout
|
||||
|
||||
```
|
||||
posterg-website/
|
||||
├── public/ # DocumentRoot - publicly accessible files
|
||||
│ ├── index.php # Front controller
|
||||
│ ├── assets/ # Public assets (CSS, JS, images)
|
||||
│ │ ├── css/
|
||||
│ │ ├── js/
|
||||
│ │ └── images/
|
||||
│ └── .htaccess # Apache/nginx rules
|
||||
│
|
||||
├── src/ # Application source code (private)
|
||||
│ ├── Controller/ # Controllers
|
||||
│ ├── Model/ # Models
|
||||
│ ├── View/ # Views/templates
|
||||
│ ├── Service/ # Business logic services
|
||||
│ ├── Repository/ # Data access layer
|
||||
│ └── Middleware/ # Middleware components
|
||||
│
|
||||
├── config/ # Configuration files (private)
|
||||
│ ├── app.php
|
||||
│ ├── database.php
|
||||
│ ├── routes.php
|
||||
│ └── .env.example # Environment variables template
|
||||
│
|
||||
├── database/ # Database-related files
|
||||
│ ├── migrations/ # Database migrations
|
||||
│ ├── seeds/ # Database seeders
|
||||
│ └── schema.sql # Database schema
|
||||
│
|
||||
├── tests/ # Unit and integration tests
|
||||
│ ├── Unit/
|
||||
│ ├── Integration/
|
||||
│ └── bootstrap.php
|
||||
│
|
||||
├── vendor/ # Third-party dependencies (Composer)
|
||||
│ └── autoload.php
|
||||
│
|
||||
├── bin/ # Executable scripts
|
||||
│ └── console # CLI commands
|
||||
│
|
||||
├── var/ # Variable/temporary files (private)
|
||||
│ ├── cache/ # Application cache
|
||||
│ ├── logs/ # Log files
|
||||
│ └── tmp/ # Temporary files
|
||||
│
|
||||
├── docs/ # Documentation
|
||||
│ └── *.md
|
||||
│
|
||||
├── scripts/ # Build/deployment scripts
|
||||
│ └── deploy.sh
|
||||
│
|
||||
├── resources/ # Non-PHP resources (private)
|
||||
│ ├── views/ # Template files
|
||||
│ ├── lang/ # Translations
|
||||
│ └── emails/ # Email templates
|
||||
│
|
||||
├── lib/ # Internal libraries (if not using src/)
|
||||
│
|
||||
├── .git/ # Git repository
|
||||
├── .gitignore
|
||||
├── composer.json # Composer dependencies
|
||||
├── composer.lock
|
||||
├── phpunit.xml # PHPUnit configuration
|
||||
├── README.md # Project documentation
|
||||
└── LICENSE # License file
|
||||
```
|
||||
|
||||
## Directory Purposes
|
||||
|
||||
### **public/** (PUBLIC - DocumentRoot points here)
|
||||
- **Only directory accessible via web browser**
|
||||
- Contains: front controller (index.php), assets (CSS/JS/images)
|
||||
- Web server DocumentRoot should point to this directory
|
||||
- Security: No sensitive files here
|
||||
|
||||
### **src/** (PRIVATE)
|
||||
- Application source code
|
||||
- All classes following PSR-4 autoloading
|
||||
- Organized by responsibility (Controller, Model, Service, etc.)
|
||||
- Not accessible from the web
|
||||
|
||||
### **config/** (PRIVATE)
|
||||
- Configuration files
|
||||
- Database credentials, API keys, app settings
|
||||
- `.env` file for environment-specific configuration
|
||||
- Never committed sensitive values (use `.env.example`)
|
||||
|
||||
### **database/** (PRIVATE)
|
||||
- Database migrations, seeds, schema definitions
|
||||
- Version-controlled database structure
|
||||
|
||||
### **tests/** (PRIVATE)
|
||||
- PHPUnit tests
|
||||
- Organized by test type (Unit, Integration, Functional)
|
||||
- Mirror the `src/` structure
|
||||
|
||||
### **vendor/** (PRIVATE)
|
||||
- Composer dependencies
|
||||
- Auto-generated, excluded from version control
|
||||
- Contains `autoload.php` for autoloading
|
||||
|
||||
### **bin/** (PRIVATE)
|
||||
- Executable scripts and CLI commands
|
||||
- Make scripts executable: `chmod +x bin/*`
|
||||
|
||||
### **var/** (PRIVATE)
|
||||
- Runtime-generated files
|
||||
- cache/, logs/, tmp/
|
||||
- Typically .gitignored (except .gitkeep files)
|
||||
- Needs write permissions
|
||||
|
||||
### **docs/** (PRIVATE)
|
||||
- Project documentation
|
||||
- API docs, guides, architecture decisions
|
||||
|
||||
### **scripts/** (PRIVATE)
|
||||
- Build, deployment, maintenance scripts
|
||||
- Not part of the application runtime
|
||||
|
||||
### **resources/** (PRIVATE)
|
||||
- Non-PHP application resources
|
||||
- Templates, translations, email layouts
|
||||
|
||||
## Migration from Current Structure
|
||||
|
||||
Your current structure → Recommended structure:
|
||||
|
||||
```
|
||||
Current → Recommended
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
index.php → public/index.php
|
||||
memoire.php → public/memoire.php OR src/Controller/
|
||||
search.php → public/search.php OR src/Controller/
|
||||
assets/ → public/assets/
|
||||
inc/ → src/ OR config/
|
||||
admin/ → src/Admin/ OR public/admin/
|
||||
database/ → database/ (keep as-is)
|
||||
tests/ → tests/ (keep as-is)
|
||||
vendor/ → vendor/ (keep as-is)
|
||||
lib/ → lib/ OR src/
|
||||
docs/ → docs/ (keep as-is)
|
||||
scripts/ → scripts/ (keep as-is)
|
||||
nginx/ → scripts/nginx/ OR config/nginx/
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **DocumentRoot = public/**
|
||||
- Configure web server to serve only from `public/`
|
||||
- All other directories are above DocumentRoot
|
||||
|
||||
2. **Sensitive Files**
|
||||
- Keep `.env`, config files outside `public/`
|
||||
- Never commit passwords, API keys
|
||||
- Use `.env.example` for templates
|
||||
|
||||
3. **Permissions**
|
||||
```bash
|
||||
# Private directories (not writable by web server)
|
||||
chmod 755 src/ config/ database/ tests/
|
||||
|
||||
# Writable by web server
|
||||
chmod 775 var/cache/ var/logs/ var/tmp/
|
||||
```
|
||||
|
||||
4. **.gitignore**
|
||||
```
|
||||
/vendor/
|
||||
/var/cache/*
|
||||
/var/logs/*
|
||||
/var/tmp/*
|
||||
/.env
|
||||
composer.lock
|
||||
```
|
||||
|
||||
## Web Server Configuration
|
||||
|
||||
### Nginx
|
||||
```nginx
|
||||
server {
|
||||
root /path/to/posterg-website/public;
|
||||
index index.php;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass unix:/var/run/php/php-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Apache (.htaccess in public/)
|
||||
```apache
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
```
|
||||
|
||||
## Composer Configuration
|
||||
|
||||
Update `composer.json` to use PSR-4 autoloading:
|
||||
|
||||
```json
|
||||
{
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Create `public/` directory
|
||||
2. Move web-accessible files to `public/`
|
||||
3. Organize classes into `src/` with namespaces
|
||||
4. Move configuration to `config/`
|
||||
5. Update web server DocumentRoot
|
||||
6. Update paths in application code
|
||||
7. Run `composer dump-autoload`
|
||||
8. Test the application
|
||||
|
||||
## References
|
||||
|
||||
- [Standard PHP Package Skeleton](https://github.com/php-pds/skeleton)
|
||||
- [PSR-4 Autoloading](https://www.php-fig.org/psr/psr-4/)
|
||||
- [Composer Documentation](https://getcomposer.org/doc/)
|
||||
381
docs/MIGRATION_CHECKLIST.md
Normal file
381
docs/MIGRATION_CHECKLIST.md
Normal file
@@ -0,0 +1,381 @@
|
||||
# Migration Checklist - Public Directory Structure
|
||||
|
||||
Quick reference for migrating from current flat structure to secure public/ structure.
|
||||
|
||||
## 📋 Summary of Required Changes
|
||||
|
||||
### 1. Dev Server (justfile) ⚡
|
||||
**Line 51** - Change from:
|
||||
```just
|
||||
@php -S 127.0.0.1:8000
|
||||
```
|
||||
To:
|
||||
```just
|
||||
@php -S 127.0.0.1:8000 -t public/
|
||||
```
|
||||
|
||||
### 2. Deployment (justfile) 📤
|
||||
**Lines 56-75** - Replace entire `deploy` recipe with two-step deployment:
|
||||
- Deploy app to `/var/www/posterg/` (not `/var/www/html/`)
|
||||
- Nginx serves from `/var/www/posterg/public/`
|
||||
|
||||
See `DEPLOYMENT_MIGRATION.md` for complete updated recipe.
|
||||
|
||||
### 3. Nginx Configuration 🔧
|
||||
**nginx/posterg.conf line 14** - Change from:
|
||||
```nginx
|
||||
root /var/www/html;
|
||||
```
|
||||
To:
|
||||
```nginx
|
||||
root /var/www/posterg/public;
|
||||
```
|
||||
|
||||
**Also update admin location** (line 58) - Change from:
|
||||
```nginx
|
||||
location ^~ /formulaire/ {
|
||||
```
|
||||
To:
|
||||
```nginx
|
||||
location ^~ /admin/ {
|
||||
```
|
||||
(Since you're moving admin/ to public/admin/)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Migration (Local Dev)
|
||||
|
||||
```bash
|
||||
# 1. Update justfile serve command
|
||||
sed -i 's/@php -S 127.0.0.1:8000/@php -S 127.0.0.1:8000 -t public\//' justfile
|
||||
|
||||
# 2. Test new dev server
|
||||
just serve
|
||||
# Visit http://localhost:8000
|
||||
# Verify http://localhost:8000/database/test.db returns 404
|
||||
|
||||
# 3. If it works, you're ready for production migration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 File Movements (Do This After Testing)
|
||||
|
||||
```bash
|
||||
# Create new structure
|
||||
mkdir -p public/{admin,assets}
|
||||
mkdir -p src config var/{cache,logs,tmp}
|
||||
|
||||
# Move public files
|
||||
mv index.php search.php memoire.php public/
|
||||
mv admin/* public/admin/ && rmdir admin
|
||||
mv assets/* public/assets/ && rmdir assets
|
||||
|
||||
# Move private files
|
||||
mv inc/* config/ && rmdir inc
|
||||
# OR if inc/ contains classes:
|
||||
# mv inc/* src/ && rmdir inc
|
||||
|
||||
# Keep these as-is
|
||||
# database/ (already private)
|
||||
# vendor/ (already private)
|
||||
# tests/ (already private)
|
||||
# lib/ (decide if it goes to src/lib or stays)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Critical Changes Required
|
||||
|
||||
### In nginx/posterg.conf:
|
||||
|
||||
1. **Line 14** - DocumentRoot
|
||||
```nginx
|
||||
# BEFORE
|
||||
root /var/www/html;
|
||||
|
||||
# AFTER
|
||||
root /var/www/posterg/public;
|
||||
```
|
||||
|
||||
2. **Line 58-76** - Admin location (already at `/formulaire/`, might want `/admin/`)
|
||||
```nginx
|
||||
# BEFORE
|
||||
location ^~ /formulaire/ {
|
||||
auth_basic "Admin Access - Post-ERG";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd-posterg;
|
||||
# ... rest of config
|
||||
}
|
||||
|
||||
# AFTER (if renaming to /admin/)
|
||||
location ^~ /admin/ {
|
||||
auth_basic "Admin Access - Post-ERG";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd-posterg;
|
||||
# ... rest of config
|
||||
}
|
||||
```
|
||||
|
||||
3. **Remove/update deny rules** (lines 48-60) - These become redundant!
|
||||
```nginx
|
||||
# BEFORE - needed because everything in DocumentRoot
|
||||
location ^~ /database/ { deny all; }
|
||||
location ^~ /shared/ { deny all; }
|
||||
location ^~ /data/ { deny all; }
|
||||
|
||||
# AFTER - can remove! They're already outside public/
|
||||
# But keep as defense-in-depth:
|
||||
location ^~ /database/ { deny all; } # Will never match, but safe
|
||||
```
|
||||
|
||||
### In justfile:
|
||||
|
||||
**Complete replacement for lines 40-76:**
|
||||
|
||||
```just
|
||||
[group('dev')]
|
||||
serve:
|
||||
@echo "🚀 Starting Post-ERG development server"
|
||||
@echo "========================================"
|
||||
@echo ""
|
||||
@echo "📍 Public site: http://localhost:8000"
|
||||
@echo "📍 Admin panel: http://localhost:8000/admin/"
|
||||
@echo ""
|
||||
@echo "🔒 Serving from public/ directory (matches production)"
|
||||
@if [ -d "vendor/php-live-reload" ]; then \
|
||||
echo "✨ Live reload enabled"; \
|
||||
else \
|
||||
echo "💡 Tip: Run 'just setup' to enable live reload"; \
|
||||
fi
|
||||
@echo ""
|
||||
@echo "Press Ctrl+C to stop"
|
||||
@echo ""
|
||||
@php -S 127.0.0.1:8000 -t public/
|
||||
|
||||
[group('deploy')]
|
||||
deploy:
|
||||
@echo "📤 Deploying Post-ERG complete site"
|
||||
@echo "===================================="
|
||||
@echo ""
|
||||
@echo "Deploying to /var/www/posterg/..."
|
||||
rsync -vur --progress \
|
||||
--chown="www-data:posterg" \
|
||||
--exclude 'vendor' \
|
||||
--exclude 'tests' \
|
||||
--exclude 'test.db' \
|
||||
--exclude '*.md' \
|
||||
--exclude '.git*' \
|
||||
--exclude '.jj' \
|
||||
--exclude '.DS_Store' \
|
||||
--exclude 'justfile*' \
|
||||
--exclude 'setup-dev.sh' \
|
||||
--exclude 'database/backup_*' \
|
||||
--exclude 'database/fixtures' \
|
||||
--exclude 'var/cache/*' \
|
||||
--exclude 'var/logs/*' \
|
||||
./ posterg:/var/www/posterg/
|
||||
@echo ""
|
||||
@echo "Setting up directories and permissions..."
|
||||
ssh posterg "cd /var/www/posterg && \
|
||||
mkdir -p var/{cache,logs,tmp} && \
|
||||
chown -R www-data:posterg var/ database/ && \
|
||||
chmod -R 775 var/ database/ && \
|
||||
chmod 660 database/*.db"
|
||||
@echo ""
|
||||
@echo "✅ Deployment complete!"
|
||||
@echo ""
|
||||
@echo "🔍 Verify:"
|
||||
@echo " • Public: https://posterg.erg.be/"
|
||||
@echo " • Admin: https://posterg.erg.be/admin/"
|
||||
|
||||
[group('deploy')]
|
||||
test-deploy:
|
||||
@echo "⚠️ Deploying test database"
|
||||
ssh posterg "mkdir -p /var/www/posterg/database"
|
||||
rsync -vur --progress ./database/test.db posterg:/var/www/posterg/database/
|
||||
ssh posterg "chown www-data:posterg /var/www/posterg/database/test.db && \
|
||||
chmod 660 /var/www/posterg/database/test.db"
|
||||
@echo "✅ Test database deployed"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Steps
|
||||
|
||||
### 1. Test Local Dev Server
|
||||
```bash
|
||||
# Start server with new -t public/ flag
|
||||
just serve
|
||||
|
||||
# In another terminal:
|
||||
curl http://localhost:8000/ # ✅ Should work
|
||||
curl http://localhost:8000/admin/ # ✅ Should work (after moving)
|
||||
curl http://localhost:8000/database/test.db # ❌ Should 404
|
||||
curl http://localhost:8000/config/ # ❌ Should 404
|
||||
curl http://localhost:8000/vendor/ # ❌ Should 404
|
||||
```
|
||||
|
||||
### 2. Test After File Migration
|
||||
```bash
|
||||
# After moving files to public/
|
||||
just serve
|
||||
|
||||
# Test again
|
||||
curl http://localhost:8000/ # ✅ index.php serves
|
||||
curl http://localhost:8000/search.php # ✅ works
|
||||
curl http://localhost:8000/admin/ # ✅ works
|
||||
curl http://localhost:8000/assets/css/style.css # ✅ works
|
||||
|
||||
# Verify old paths don't work
|
||||
curl http://localhost:8000/../database/test.db # ❌ 404
|
||||
curl http://localhost:8000/../config/ # ❌ 404
|
||||
```
|
||||
|
||||
### 3. Test Production Deployment
|
||||
```bash
|
||||
# After deploying to server
|
||||
just server-status
|
||||
|
||||
# Manual checks
|
||||
curl -I https://posterg.erg.be/
|
||||
curl -I https://posterg.erg.be/admin/
|
||||
curl -I https://posterg.erg.be/database/test.db # Must be 404!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 PHP Path Updates Needed
|
||||
|
||||
After moving to public/, update PHP includes:
|
||||
|
||||
**Before (from root):**
|
||||
```php
|
||||
<?php
|
||||
require_once 'inc/config.php';
|
||||
require_once 'lib/Database.php';
|
||||
require_once 'database/test.db';
|
||||
```
|
||||
|
||||
**After (from public/):**
|
||||
```php
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/config.php';
|
||||
require_once __DIR__ . '/../src/lib/Database.php';
|
||||
$db = new PDO('sqlite:' . __DIR__ . '/../database/test.db');
|
||||
```
|
||||
|
||||
**Or use a bootstrap:**
|
||||
```php
|
||||
<?php
|
||||
// public/index.php
|
||||
require_once __DIR__ . '/../config/bootstrap.php';
|
||||
|
||||
// config/bootstrap.php
|
||||
define('APP_ROOT', dirname(__DIR__));
|
||||
define('PUBLIC_ROOT', APP_ROOT . '/public');
|
||||
define('DATABASE_PATH', APP_ROOT . '/database/test.db');
|
||||
|
||||
require_once APP_ROOT . '/vendor/autoload.php';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 What to Check in Your Code
|
||||
|
||||
Run these searches to find hardcoded paths:
|
||||
|
||||
```bash
|
||||
# Find absolute paths
|
||||
grep -r "/var/www/html" ./*.php
|
||||
grep -r "/var/www/html" ./admin/*.php
|
||||
|
||||
# Find relative paths that need updating
|
||||
grep -r "require.*inc/" ./*.php
|
||||
grep -r "require.*lib/" ./*.php
|
||||
grep -r "require.*database/" ./*.php
|
||||
|
||||
# Find database connections
|
||||
grep -r "\.db" ./*.php
|
||||
|
||||
# Find asset references
|
||||
grep -r "src=\"assets/" ./*.php
|
||||
grep -r "href=\"assets/" ./*.php
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Quick Start (Minimal Changes First)
|
||||
|
||||
If you want to test with minimal changes:
|
||||
|
||||
**1. Only change dev server:**
|
||||
```bash
|
||||
# Edit justfile line 51
|
||||
@php -S 127.0.0.1:8000 -t public/
|
||||
|
||||
# Create public/ with symlinks (temporary test)
|
||||
mkdir public
|
||||
ln -s ../index.php public/index.php
|
||||
ln -s ../search.php public/search.php
|
||||
ln -s ../admin public/admin
|
||||
ln -s ../assets public/assets
|
||||
|
||||
# Test
|
||||
just serve
|
||||
```
|
||||
|
||||
**2. If it works, do full migration**
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Rollback Plan
|
||||
|
||||
If production deployment fails:
|
||||
|
||||
```bash
|
||||
# On server
|
||||
sudo systemctl stop nginx
|
||||
|
||||
# Restore old config
|
||||
sudo cp /etc/nginx/sites-available/posterg.backup /etc/nginx/sites-available/posterg
|
||||
sudo nginx -t
|
||||
sudo systemctl start nginx
|
||||
|
||||
# Or restore files
|
||||
sudo rm -rf /var/www/posterg
|
||||
sudo mv /var/www/html.backup /var/www/html
|
||||
```
|
||||
|
||||
**Always backup before deploying:**
|
||||
```bash
|
||||
# Before migration
|
||||
ssh posterg "sudo cp -r /var/www/html /var/www/html.backup"
|
||||
ssh posterg "sudo cp /etc/nginx/sites-available/posterg /etc/nginx/sites-available/posterg.backup"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Benefits After Migration
|
||||
|
||||
| Before | After |
|
||||
|--------|-------|
|
||||
| ❌ All files in DocumentRoot | ✅ Only public/ in DocumentRoot |
|
||||
| ❌ Database accessible if nginx misconfigured | ✅ Database physically unreachable |
|
||||
| ❌ Config files one deny rule away | ✅ Config files outside web root |
|
||||
| ❌ 20+ deny/exclude rules needed | ✅ Physical separation, minimal rules |
|
||||
| ❌ Dev server exposes everything | ✅ Dev matches production security |
|
||||
|
||||
---
|
||||
|
||||
## Next: Check Your Current Paths
|
||||
|
||||
Run this to see what paths need updating:
|
||||
```bash
|
||||
# Find all require/include statements
|
||||
find . -name "*.php" -not -path "./vendor/*" -not -path "./tests/*" \
|
||||
-exec grep -H "require\|include" {} \; > paths-audit.txt
|
||||
|
||||
# Review paths-audit.txt and update paths
|
||||
cat paths-audit.txt
|
||||
```
|
||||
|
||||
See **DEPLOYMENT_MIGRATION.md** for complete implementation details.
|
||||
214
docs/MIGRATION_COMPLETE.md
Normal file
214
docs/MIGRATION_COMPLETE.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# ✅ Migration to public/ Directory Structure - COMPLETE
|
||||
|
||||
## 📊 Summary of Changes
|
||||
|
||||
### Directory Structure Created
|
||||
```
|
||||
posterg-website/
|
||||
├── config/ # ✅ NEW - Configuration files
|
||||
│ └── bootstrap.php # Central path management
|
||||
├── public/ # ✅ NEW - DocumentRoot (web-accessible)
|
||||
│ ├── admin/ # Moved from /admin/
|
||||
│ ├── assets/ # Moved from /assets/
|
||||
│ ├── index.php # Moved from /index.php
|
||||
│ ├── search.php # Moved from /search.php
|
||||
│ └── memoire.php # Moved from /memoire.php
|
||||
├── resources/ # ✅ NEW - Application resources
|
||||
│ └── views/ # Moved from /inc/
|
||||
│ ├── header.php
|
||||
│ └── footer.php
|
||||
├── var/ # ✅ NEW - Runtime files
|
||||
│ ├── cache/
|
||||
│ ├── logs/
|
||||
│ └── tmp/
|
||||
├── database/ # ✅ KEPT - Now private
|
||||
├── lib/ # ✅ KEPT - Now private
|
||||
├── vendor/ # ✅ KEPT - Now private
|
||||
└── tests/ # ✅ KEPT - Now private
|
||||
```
|
||||
|
||||
### Files Modified
|
||||
|
||||
**1. config/bootstrap.php** (NEW)
|
||||
- Central path configuration
|
||||
- Defines APP_ROOT, PUBLIC_ROOT, DATABASE_PATH, etc.
|
||||
- Helper functions: view(), getDatabase()
|
||||
- Environment detection (dev vs production)
|
||||
- Error handling configuration
|
||||
|
||||
**2. public/*.php** (3 files updated)
|
||||
- index.php: Uses bootstrap, updated require paths
|
||||
- search.php: Uses bootstrap, updated require paths
|
||||
- memoire.php: Uses bootstrap, updated require paths
|
||||
- All now use view() helper for header/footer
|
||||
|
||||
**3. public/admin/*.php** (7 files updated)
|
||||
- add.php, edit.php, formulaire.php, import.php
|
||||
- index.php, publish.php, thanks.php
|
||||
- All updated to use ../../ paths for lib access
|
||||
- Bootstrap added where needed
|
||||
|
||||
**4. justfile** (Updated)
|
||||
- Dev server: `php -S 127.0.0.1:8000 -t public/`
|
||||
- Deploy: Now deploys to `/var/www/posterg/`
|
||||
- Database deploy: Updated paths to `/var/www/posterg/`
|
||||
- Nginx deploy: Checks for correct DocumentRoot
|
||||
|
||||
**5. nginx/posterg.conf** (Updated)
|
||||
- DocumentRoot: `/var/www/html` → `/var/www/posterg/public`
|
||||
- Admin location: `/formulaire/` → `/admin/`
|
||||
|
||||
**6. .gitignore** (Updated)
|
||||
- Added var/ directory patterns
|
||||
- Keeps .gitkeep files, ignores contents
|
||||
|
||||
### Security Improvements
|
||||
|
||||
**Before:**
|
||||
- ❌ All files in DocumentRoot (/var/www/html/)
|
||||
- ❌ Database accessible at /database/test.db
|
||||
- ❌ Config files accessible
|
||||
- ❌ Dev server exposed everything
|
||||
- ❌ Relied on nginx deny rules
|
||||
|
||||
**After:**
|
||||
- ✅ Only public/ in DocumentRoot
|
||||
- ✅ Database physically outside web root
|
||||
- ✅ Config files physically private
|
||||
- ✅ Dev server matches production security
|
||||
- ✅ Physical separation = secure by default
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Local Development
|
||||
```bash
|
||||
# Start dev server
|
||||
just serve
|
||||
|
||||
# Test in browser:
|
||||
# - http://localhost:8000/ → Should work
|
||||
# - http://localhost:8000/admin/ → Should work
|
||||
# - http://localhost:8000/database/test.db → Should 404 ✅
|
||||
# - http://localhost:8000/config/ → Should 404 ✅
|
||||
# - http://localhost:8000/../database/test.db → Should 404 ✅
|
||||
```
|
||||
|
||||
### Security Verification
|
||||
```bash
|
||||
# These should all return 404:
|
||||
curl http://localhost:8000/database/test.db
|
||||
curl http://localhost:8000/config/bootstrap.php
|
||||
curl http://localhost:8000/vendor/autoload.php
|
||||
curl http://localhost:8000/../database/test.db
|
||||
curl http://localhost:8000/lib/Database.php
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
|
||||
**BEFORE deploying to production:**
|
||||
|
||||
1. **Update nginx config on server:**
|
||||
```bash
|
||||
# Edit /etc/nginx/sites-available/posterg
|
||||
# Change: root /var/www/html;
|
||||
# To: root /var/www/posterg/public;
|
||||
```
|
||||
|
||||
2. **Create new directory on server:**
|
||||
```bash
|
||||
ssh posterg "sudo mkdir -p /var/www/posterg"
|
||||
```
|
||||
|
||||
3. **Deploy application:**
|
||||
```bash
|
||||
just deploy
|
||||
```
|
||||
|
||||
4. **Deploy nginx config:**
|
||||
```bash
|
||||
just deploy-nginx
|
||||
# Then on server:
|
||||
ssh posterg
|
||||
sudo bash /tmp/deploy-production.sh
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
5. **Verify:**
|
||||
```bash
|
||||
just server-status
|
||||
curl -I https://posterg.erg.be/
|
||||
curl -I https://posterg.erg.be/admin/
|
||||
curl -I https://posterg.erg.be/database/test.db # Must 404!
|
||||
```
|
||||
|
||||
## 📝 Path Reference
|
||||
|
||||
### From public/*.php files:
|
||||
```php
|
||||
<?php
|
||||
require_once __DIR__ . '/../config/bootstrap.php'; // Bootstrap
|
||||
require_once LIB_ROOT . '/Database.php'; // Library
|
||||
$db = getDatabase(); // Database
|
||||
view('header.php', ['pageTitle' => 'Title']); // Template
|
||||
```
|
||||
|
||||
### From public/admin/*.php files:
|
||||
```php
|
||||
<?php
|
||||
require_once __DIR__ . '/../../config/bootstrap.php'; // Bootstrap
|
||||
require_once LIB_ROOT . '/Database.php'; // Library
|
||||
```
|
||||
|
||||
### Available Constants (from bootstrap):
|
||||
- `APP_ROOT` - /path/to/posterg-website
|
||||
- `PUBLIC_ROOT` - /path/to/posterg-website/public
|
||||
- `CONFIG_ROOT` - /path/to/posterg-website/config
|
||||
- `DATABASE_ROOT` - /path/to/posterg-website/database
|
||||
- `DATABASE_PATH` - /path/to/posterg-website/database/test.db
|
||||
- `RESOURCES_ROOT` - /path/to/posterg-website/resources
|
||||
- `LIB_ROOT` - /path/to/posterg-website/lib
|
||||
- `VAR_ROOT` - /path/to/posterg-website/var
|
||||
- `CACHE_ROOT` - /path/to/posterg-website/var/cache
|
||||
- `LOGS_ROOT` - /path/to/posterg-website/var/logs
|
||||
- `VIEWS_ROOT` - /path/to/posterg-website/resources/views
|
||||
|
||||
## 🎯 Next Steps
|
||||
|
||||
1. ✅ Migration complete - verify locally
|
||||
2. ⏭️ Test dev server: `just serve`
|
||||
3. ⏭️ Test all pages work correctly
|
||||
4. ⏭️ Update nginx config on production server
|
||||
5. ⏭️ Deploy to production: `just deploy`
|
||||
6. ⏭️ Deploy nginx config: `just deploy-nginx`
|
||||
7. ⏭️ Verify production deployment
|
||||
|
||||
## 🔄 Rollback (if needed)
|
||||
|
||||
If something goes wrong, jj makes it easy:
|
||||
|
||||
```bash
|
||||
# View history
|
||||
jj log
|
||||
|
||||
# Go back to previous state
|
||||
jj edit <previous-change-id>
|
||||
|
||||
# Or abandon current changes
|
||||
jj abandon @
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
See also:
|
||||
- `DIRECTORY_STRUCTURE.md` - Full structure reference
|
||||
- `DEPLOYMENT_MIGRATION.md` - Detailed migration guide
|
||||
- `MIGRATION_CHECKLIST.md` - Quick checklist
|
||||
|
||||
## ✨ Benefits Achieved
|
||||
|
||||
1. **Security**: Private files physically separated from public
|
||||
2. **Standards**: Follows PHP-FIG and Standard PHP Package Skeleton
|
||||
3. **Development**: Dev server matches production security
|
||||
4. **Maintainability**: Clear separation of concerns
|
||||
5. **Portability**: Path constants make relocation easy
|
||||
6. **Best Practices**: Industry-standard directory structure
|
||||
118
docs/SERVER_SETUP.md
Normal file
118
docs/SERVER_SETUP.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Server Setup (Manual)
|
||||
|
||||
Since sudo prompts don't work over SSH in justfile, do the initial setup manually.
|
||||
|
||||
## One-Time Setup on Server
|
||||
|
||||
```bash
|
||||
# 1. SSH to server
|
||||
ssh posterg
|
||||
|
||||
# 2. Backup current site (recommended)
|
||||
sudo cp -r /var/www/html /var/www/html.backup
|
||||
|
||||
# 3. Create new directory structure
|
||||
sudo mkdir -p /var/www/posterg
|
||||
|
||||
# 4. Set ownership (www-data is the web server user)
|
||||
sudo chown www-data:posterg /var/www/posterg
|
||||
|
||||
# 5. Set permissions (775 = rwxrwxr-x)
|
||||
sudo chmod 775 /var/www/posterg
|
||||
|
||||
# 6. Verify
|
||||
ls -ld /var/www/posterg
|
||||
# Should show: drwxrwxr-x 2 www-data posterg 4096 ... /var/www/posterg
|
||||
|
||||
# 7. Exit server
|
||||
exit
|
||||
```
|
||||
|
||||
## Deploy from Local Machine
|
||||
|
||||
```bash
|
||||
just deploy
|
||||
```
|
||||
|
||||
## Complete Deployment Process
|
||||
|
||||
```bash
|
||||
# On server (one time)
|
||||
ssh posterg
|
||||
sudo mkdir -p /var/www/posterg
|
||||
sudo chown www-data:posterg /var/www/posterg
|
||||
sudo chmod 775 /var/www/posterg
|
||||
exit
|
||||
|
||||
# From local machine
|
||||
just deploy # Deploy files
|
||||
just deploy-nginx # Update nginx config
|
||||
|
||||
# On server - apply nginx config
|
||||
ssh posterg
|
||||
sudo bash /tmp/deploy-production.sh
|
||||
sudo systemctl reload nginx
|
||||
exit
|
||||
|
||||
# Verify from local
|
||||
just server-status
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **Don't delete `/var/www/html/` yet!** Keep it as backup until you confirm the new structure works
|
||||
- The new structure uses `/var/www/posterg/public/` as DocumentRoot
|
||||
- Nginx must be updated to point to the new location
|
||||
|
||||
## After Confirming Everything Works
|
||||
|
||||
Once you've verified the new deployment works:
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo rm -rf /var/www/html.backup # Remove backup if no longer needed
|
||||
sudo rm -rf /var/www/html # Remove old directory
|
||||
```
|
||||
|
||||
## Directory Structure on Server
|
||||
|
||||
```
|
||||
/var/www/
|
||||
├── html/ ← OLD (keep as backup for now)
|
||||
├── html.backup/ ← BACKUP (can delete later)
|
||||
└── posterg/ ← NEW
|
||||
├── public/ ← DocumentRoot (nginx serves from here)
|
||||
├── includes/
|
||||
├── config/
|
||||
├── database/
|
||||
├── lib/
|
||||
└── vendor/
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Permission denied during deploy
|
||||
**Cause:** Directory doesn't exist or has wrong ownership
|
||||
**Fix:** Run the setup commands above
|
||||
|
||||
### Nginx 403 Forbidden
|
||||
**Cause:** Wrong permissions on files
|
||||
**Fix:**
|
||||
```bash
|
||||
ssh posterg
|
||||
cd /var/www/posterg
|
||||
sudo chown -R www-data:posterg .
|
||||
sudo find . -type d -exec chmod 755 {} \;
|
||||
sudo find . -type f -exec chmod 644 {} \;
|
||||
sudo chmod 775 database/
|
||||
sudo chmod 660 database/*.db
|
||||
```
|
||||
|
||||
### Database connection errors
|
||||
**Cause:** Database file permissions
|
||||
**Fix:**
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo chown www-data:posterg /var/www/posterg/database/test.db
|
||||
sudo chmod 660 /var/www/posterg/database/test.db
|
||||
```
|
||||
182
docs/SIMPLIFICATION.md
Normal file
182
docs/SIMPLIFICATION.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# Website Structure Simplification
|
||||
|
||||
## Problem Identified
|
||||
|
||||
The initial migration used the **Standard PHP Package Skeleton**, which is designed for **reusable PHP packages/libraries** (like Composer packages), not for websites.
|
||||
|
||||
This resulted in:
|
||||
- ❌ Overcomplicated structure (`var/`, `resources/`, complex bootstrap)
|
||||
- ❌ Unused directories (`var/cache/`, `var/logs/`, `var/tmp/`)
|
||||
- ❌ Package-oriented naming (`resources/views/`)
|
||||
- ❌ Unnecessary constants and helper functions
|
||||
|
||||
## Solution: Simplified for Website
|
||||
|
||||
### Removed
|
||||
|
||||
1. **`var/` directory** - Completely unused, only needed for complex applications with:
|
||||
- Custom caching systems
|
||||
- Application-level logging
|
||||
- Temporary file processing
|
||||
|
||||
2. **`resources/` directory** - Package-oriented name, renamed to simple `includes/`
|
||||
|
||||
3. **Complex bootstrap** - Removed unused constants:
|
||||
- `VAR_ROOT`, `CACHE_ROOT`, `LOGS_ROOT`
|
||||
- `PUBLIC_ROOT`, `CONFIG_ROOT`, `RESOURCES_ROOT`
|
||||
- `view()` helper function
|
||||
|
||||
### Simplified Structure
|
||||
|
||||
```
|
||||
posterg-website/
|
||||
├── public/ # DocumentRoot (web-accessible) ✅
|
||||
│ ├── index.php
|
||||
│ ├── search.php
|
||||
│ ├── memoire.php
|
||||
│ ├── admin/
|
||||
│ └── assets/
|
||||
│
|
||||
├── includes/ # Simple template includes ✅
|
||||
│ ├── header.php
|
||||
│ └── footer.php
|
||||
│
|
||||
├── config/ # Minimal configuration ✅
|
||||
│ └── bootstrap.php (simplified)
|
||||
│
|
||||
├── database/ # Database files (private)
|
||||
│ └── test.db
|
||||
│
|
||||
├── lib/ # PHP classes (private)
|
||||
│ ├── Database.php
|
||||
│ ├── RateLimit.php
|
||||
│ └── cache/rate_limit/ (used by RateLimit)
|
||||
│
|
||||
├── vendor/ # Composer dependencies (private)
|
||||
└── tests/ # Tests (private)
|
||||
```
|
||||
|
||||
### Simplified config/bootstrap.php
|
||||
|
||||
**Before:** 66 lines with many unused constants
|
||||
**After:** 33 lines with only essentials
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Define application root
|
||||
define('APP_ROOT', dirname(__DIR__));
|
||||
|
||||
// Database path
|
||||
define('DATABASE_PATH', APP_ROOT . '/database/test.db');
|
||||
|
||||
// Error reporting (dev vs production)
|
||||
if (php_sapi_name() === 'cli-server') {
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', '1');
|
||||
} else {
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', '0');
|
||||
}
|
||||
|
||||
// Simple helper for templates
|
||||
function include_template($name) {
|
||||
include APP_ROOT . '/includes/' . $name;
|
||||
}
|
||||
|
||||
// Composer autoload
|
||||
if (file_exists(APP_ROOT . '/vendor/autoload.php')) {
|
||||
require_once APP_ROOT . '/vendor/autoload.php';
|
||||
}
|
||||
```
|
||||
|
||||
### Simplified PHP Files
|
||||
|
||||
**Before:**
|
||||
```php
|
||||
require_once __DIR__ . '/../config/bootstrap.php';
|
||||
require_once LIB_ROOT . '/Database.php';
|
||||
view('header.php', ['pageTitle' => $title]);
|
||||
```
|
||||
|
||||
**After:**
|
||||
```php
|
||||
require_once __DIR__ . '/../config/bootstrap.php';
|
||||
require_once APP_ROOT . '/lib/Database.php';
|
||||
include APP_ROOT . '/includes/header.php';
|
||||
```
|
||||
|
||||
## Comparison: Package vs Website
|
||||
|
||||
| Feature | PHP Package | PHP Website (this project) |
|
||||
|---------|-------------|----------------------------|
|
||||
| Purpose | Reusable library | Single website |
|
||||
| Structure | Complex (PSR-4, namespaces) | Simple (includes, classes) |
|
||||
| Directories | `src/`, `resources/`, `var/`, `bin/` | `public/`, `includes/`, `lib/` |
|
||||
| Autoloading | PSR-4 namespaces | Simple require statements |
|
||||
| Config | Complex bootstrap with many constants | Minimal bootstrap |
|
||||
| Caching | `var/cache/` with framework | Simple file-based if needed |
|
||||
| Logging | `var/logs/` with logger | PHP error_log |
|
||||
|
||||
## Benefits of Simplification
|
||||
|
||||
### Before (Package-oriented)
|
||||
- ❌ 66-line bootstrap file
|
||||
- ❌ 10+ unused constants
|
||||
- ❌ `resources/views/` (confusing name)
|
||||
- ❌ `var/` directory (completely unused)
|
||||
- ❌ Helper functions for simple includes
|
||||
- ❌ Over-engineered for a simple website
|
||||
|
||||
### After (Website-focused)
|
||||
- ✅ 33-line bootstrap file (50% smaller)
|
||||
- ✅ 2 essential constants (APP_ROOT, DATABASE_PATH)
|
||||
- ✅ `includes/` (clear, simple name)
|
||||
- ✅ No unused directories
|
||||
- ✅ Standard PHP `include` statements
|
||||
- ✅ Appropriate for a PHP website
|
||||
|
||||
### Security (Unchanged)
|
||||
- ✅ Still uses `public/` as DocumentRoot
|
||||
- ✅ Database still outside web root
|
||||
- ✅ Config still private
|
||||
- ✅ All security improvements retained
|
||||
|
||||
## Testing
|
||||
|
||||
All PHP files pass syntax check:
|
||||
```bash
|
||||
$ php -l config/bootstrap.php # OK
|
||||
$ php -l public/index.php # OK
|
||||
$ php -l public/search.php # OK
|
||||
$ php -l public/memoire.php # OK
|
||||
$ php -l public/admin/index.php # OK
|
||||
```
|
||||
|
||||
Start dev server:
|
||||
```bash
|
||||
$ just serve
|
||||
```
|
||||
|
||||
## When You WOULD Need var/
|
||||
|
||||
You would need a `var/` directory if you were building:
|
||||
- A framework (Laravel, Symfony)
|
||||
- A CMS (WordPress, Drupal)
|
||||
- An application with:
|
||||
- Template compilation/caching
|
||||
- Session storage
|
||||
- File upload processing
|
||||
- Application-level logging
|
||||
- Queue systems
|
||||
|
||||
For your thesis website: **Not needed** ✅
|
||||
|
||||
## Conclusion
|
||||
|
||||
- ✅ Structure is now appropriate for a **PHP website**
|
||||
- ✅ Removed package-oriented complexity
|
||||
- ✅ Kept all security improvements (public/ directory)
|
||||
- ✅ Simpler, cleaner, easier to maintain
|
||||
- ✅ Still follows best practices (just the right ones)
|
||||
|
||||
The core improvement (public/ directory for security) remains intact, but now with a structure that fits a website, not a reusable package.
|
||||
Reference in New Issue
Block a user