8.7 KiB
✅ Production Deployment Complete - Post-ERG
Date: February 5, 2026
Status: ✅ Successfully Deployed
🎉 Deployment Summary
The Post-ERG website is now successfully deployed with production-ready nginx configuration and security hardening.
✅ What's Working
| Feature | Status | Test Result |
|---|---|---|
| Public Site | ✅ Working | https://posterg.erg.be/ → 200 OK |
| SSL/TLS | ✅ Working | HTTPS with valid certificate |
| Admin Panel | ✅ Protected | /formulaire/ → 401 (requires password) |
| Database Protection | ✅ Blocked | /database/ → 403 Forbidden |
| Sensitive Files | ✅ Blocked | .md, .sql files → 403 Forbidden |
| Shared Directory | ✅ Blocked | /shared/ → 403 Forbidden |
| Security Headers | ✅ Present | X-Frame-Options, CSP, etc. |
| PHP 8.4 | ✅ Running | php8.4-fpm active |
| File Permissions | ✅ Fixed | posterg group, readable by www-data |
🔧 What Was Fixed
1. File Permissions
Problem: Files owned by theophile:theophile with 640 permissions, nginx couldn't read them.
Solution:
# Changed group to posterg (www-data is member)
chown -R theophile:posterg /var/www/html/
# Set proper permissions
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 640 {} \;
2. PHP Include Paths
Problem: Public files used ../../shared/ which doesn't work in production structure.
Solution:
- Public files: Changed
../../shared/→/shared/ - Admin files: Changed
../../shared/→/../shared/ - Automated in deployment script
3. Nginx Configuration
Problem: Using basic default config with no security.
Solution: Deployed production config with:
- ✅ Rate limiting (30/min general, 10/min admin)
- ✅ File protection (database, configs, hidden files)
- ✅ Admin password protection
- ✅ Security headers
- ✅ Proper PHP-FPM configuration
- ✅ Upload size limits (100MB)
📋 Production Configuration
Server Details
- Server: posterg.erg.be
- Internal IP: 192.168.6.125
- PHP Version: 8.4.16
- Nginx: Latest stable
- SSL/TLS: Handled by upstream reverse proxy
File Structure
/var/www/html/
├── index.php, memoire.php, search.php (public files)
├── assets/ (CSS, JS)
├── shared/ (PHP libraries - blocked from web)
│ ├── Database.php
│ ├── RateLimit.php
│ └── config.php
├── database/ (SQLite database - blocked from web)
│ └── posterg.db
└── formulaire/ (admin panel - password protected)
├── index.php, list.php, edit.php
└── data/
├── theses/ (uploaded PDF files)
└── covers/ (uploaded cover images)
Security Configuration
Rate Limits:
- General requests: 30 requests/minute (burst: 20)
- Search endpoint: 30 requests/minute (burst: 10)
- Admin panel: 10 requests/minute (burst: 5)
Protected Paths:
/database/- Database files (403)/shared/- PHP libraries (403)/data/- Upload directories (403)*.dbfiles - Database files (403)*.md, *.sql, *.sh, *.json- Sensitive files (403)- Hidden files (
.git,.env, etc.) - (403)
Admin Access:
- Path:
/formulaire/ - Authentication: HTTP Basic Auth
- Password file:
/etc/nginx/.htpasswd-posterg - User:
test_posterg_22@
Security Headers:
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
🚀 Deployment Process (For Future Updates)
The deployment process has been automated and updated:
Deploy Code Changes
# Deploy public site
just deploy-public
# Automatically fixes paths: ../../shared/ → /shared/
# Deploy admin panel
just deploy-admin
# Automatically fixes paths: ../../shared/ → /../shared/
# Deploy both
just deploy
Deploy Nginx Config
# Deploy production nginx configuration
just deploy-nginx-production
# On server, run deployment script
ssh posterg
sudo bash /tmp/deploy-production.sh
The deployment scripts now automatically:
- ✅ Copy files to server
- ✅ Fix PHP include paths
- ✅ Set correct permissions
- ✅ Test nginx configuration
- ✅ Reload services
🧪 Testing & Verification
Automated Tests
# On server
cd /var/www/html
# Test public site
curl -I http://localhost/ # Should: 200 OK
# Test admin protection
curl -I http://localhost/formulaire/ # Should: 401 Unauthorized
# Test security
curl -I http://localhost/database/posterg.db # Should: 403 Forbidden
curl -I http://localhost/README.md # Should: 403 Forbidden
curl -I http://localhost/shared/Database.php # Should: 403 Forbidden
External Tests
# From your local machine
curl -I https://posterg.erg.be/ # Should: 200 OK
curl -I https://posterg.erg.be/formulaire/ # Should: 401
Browser Tests
- ✅ Visit https://posterg.erg.be/ - Homepage loads
- ✅ Search functionality works
- ✅ Individual thesis pages work
- ✅ Admin requires password: https://posterg.erg.be/formulaire/
- ✅ Can upload files in admin (after login)
📊 Monitoring
Log Files
# Nginx access log
tail -f /var/log/nginx/posterg_access.log
# Nginx error log
tail -f /var/log/nginx/posterg_error.log
# PHP error log
tail -f /var/www/html/error.log
Service Status
# Check nginx
sudo systemctl status nginx
# Check PHP-FPM
sudo systemctl status php8.4-fpm
# Test nginx config
sudo nginx -t
🔐 Admin Access
Login Credentials
- URL: https://posterg.erg.be/formulaire/
- Username:
test_posterg_22@ - Password: Set during deployment (stored securely)
Change Password
ssh posterg
sudo htpasswd /etc/nginx/.htpasswd-posterg test_posterg_22@
Add Additional Admin Users
ssh posterg
sudo htpasswd /etc/nginx/.htpasswd-posterg newusername
🔄 Maintenance
Update Website Content
# From local machine
just deploy
# Content is automatically updated on server
Reload Nginx (after config changes)
ssh posterg
sudo nginx -t # Test configuration
sudo systemctl reload nginx # Reload if test passes
Restart PHP-FPM (if needed)
ssh posterg
sudo systemctl restart php8.4-fpm
Update SSL Certificate
SSL/TLS is handled by the upstream reverse proxy. Contact the infrastructure team if certificate renewal is needed.
🆘 Troubleshooting
Site Returns 403 Forbidden
Check file permissions:
ls -la /var/www/html/index.php
# Should show: -rw-r----- theophile posterg
Check nginx user:
groups www-data
# Should show: www-data posterg
Site Returns 500 Internal Server Error
Check PHP errors:
tail -f /var/log/nginx/posterg_error.log
tail -f /var/www/html/error.log
Check PHP-FPM:
sudo systemctl status php8.4-fpm
sudo systemctl restart php8.4-fpm
Admin Panel Not Working
Check password file:
ls -la /etc/nginx/.htpasswd-posterg
Reset password:
sudo htpasswd /etc/nginx/.htpasswd-posterg test_posterg_22@
After Deploying, Site Broken
Check if paths were fixed:
grep "require_once" /var/www/html/index.php
# Should show: __DIR__ . '/shared/Database.php'
# NOT: __DIR__ . '/../../shared/Database.php'
Manually fix if needed:
ssh posterg "cd /var/www/html && sed -i \"s|__DIR__ . '/../../shared/|__DIR__ . '/shared/|g\" *.php"
📞 Support Contacts
- Deployment Issues: Check logs first
- Nginx Config:
/etc/nginx/sites-available/posterg - PHP Config:
/etc/php/8.4/fpm/pool.d/www.conf - Database:
/var/www/html/database/posterg.db
✅ Success Checklist
After any deployment, verify:
- Public site loads: https://posterg.erg.be/
- Search works
- Individual thesis pages work
- Admin requires password
- Admin can log in
- File uploads work (in admin)
- Database is protected (403)
- Sensitive files blocked (403)
- No errors in logs
- Security headers present
📚 Documentation Files
posterg-production.conf- Production nginx configurationdeploy-production.sh- Automated deployment scriptPRODUCTION_DEPLOYMENT.md- Detailed deployment guideDEPLOY_NOW.md- Quick deployment instructionsDEPLOYMENT_COMPLETE.md- This file
Deployment completed successfully on February 5, 2026 🎉