More semantically accurate: contains SQLite files, schema, fixtures, test data. Updated all references in code, scripts, docs.
9.3 KiB
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:
@php -S 127.0.0.1:8000
To:
@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:
root /var/www/html;
To:
root /var/www/posterg/public;
Also update admin location (line 58) - Change from:
location ^~ /formulaire/ {
To:
location ^~ /admin/ {
(Since you're moving admin/ to public/admin/)
🚀 Quick Migration (Local Dev)
# 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/storage/test.db returns 404
# 3. If it works, you're ready for production migration
📁 File Movements (Do This After Testing)
# 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:
- Line 14 - DocumentRoot
# BEFORE
root /var/www/html;
# AFTER
root /var/www/posterg/public;
- Line 58-76 - Admin location (already at
/formulaire/, might want/admin/)
# 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
}
- Remove/update deny rules (lines 48-60) - These become redundant!
# BEFORE - needed because everything in DocumentRoot
location ^~ /storage/ { 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 ^~ /storage/ { deny all; } # Will never match, but safe
In justfile:
Complete replacement for lines 40-76:
[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 ./storage/test.db posterg:/var/www/posterg/storage/
ssh posterg "chown www-data:posterg /var/www/posterg/storage/test.db && \
chmod 660 /var/www/posterg/storage/test.db"
@echo "✅ Test database deployed"
🧪 Testing Steps
1. Test Local Dev Server
# 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/storage/test.db # ❌ Should 404
curl http://localhost:8000/config/ # ❌ Should 404
curl http://localhost:8000/vendor/ # ❌ Should 404
2. Test After File Migration
# 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/../storage/test.db # ❌ 404
curl http://localhost:8000/../config/ # ❌ 404
3. Test Production Deployment
# 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/storage/test.db # Must be 404!
📝 PHP Path Updates Needed
After moving to public/, update PHP includes:
Before (from root):
<?php
require_once 'inc/config.php';
require_once 'lib/Database.php';
require_once 'database/test.db';
After (from public/):
<?php
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../src/lib/Database.php';
$db = new PDO('sqlite:' . __DIR__ . '/../storage/test.db');
Or use a bootstrap:
<?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 . '/storage/test.db');
require_once APP_ROOT . '/vendor/autoload.php';
🔍 What to Check in Your Code
Run these searches to find hardcoded paths:
# 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:
# 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:
# 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:
# 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:
# 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.