mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
Consolidate nginx docs and scripts, update paths
This commit is contained in:
14
README.md
14
README.md
@@ -34,7 +34,9 @@ posterg/
|
|||||||
│ ├── deploy-server.sh # Run on server with sudo to apply nginx config
|
│ ├── deploy-server.sh # Run on server with sudo to apply nginx config
|
||||||
│ └── manage-admin-users.sh # Run on server with sudo to manage htpasswd
|
│ └── manage-admin-users.sh # Run on server with sudo to manage htpasswd
|
||||||
└── nginx/ # nginx config and reference files
|
└── nginx/ # nginx config and reference files
|
||||||
└── posterg.conf
|
├── posterg.conf
|
||||||
|
├── scripts/ # Server setup scripts (password, PHP SQLite)
|
||||||
|
└── docs/ # Documentation
|
||||||
```
|
```
|
||||||
|
|
||||||
Uploaded files (PDFs, covers) live in `storage/` — outside the webroot — and are
|
Uploaded files (PDFs, covers) live in `storage/` — outside the webroot — and are
|
||||||
@@ -73,19 +75,19 @@ sudo chmod 775 /var/www/posterg
|
|||||||
exit
|
exit
|
||||||
```
|
```
|
||||||
|
|
||||||
Then deploy once, copy nginx config, and apply:
|
Then deploy once and apply nginx config:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
just deploy
|
just deploy
|
||||||
rsync -v nginx/posterg.conf posterg:/tmp/posterg.conf
|
just deploy-nginx
|
||||||
ssh posterg "sudo bash /var/www/posterg/scripts/deploy-server.sh"
|
|
||||||
ssh posterg "sudo systemctl reload nginx"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Admin users (htpasswd)
|
### Admin users (htpasswd)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ssh posterg "sudo bash /var/www/posterg/scripts/manage-admin-users.sh"
|
just manage-admin-users
|
||||||
|
# Then on server:
|
||||||
|
ssh posterg "sudo bash /tmp/manage-admin-users.sh"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Security notes
|
## Security notes
|
||||||
|
|||||||
134
SETUP.md
Normal file
134
SETUP.md
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
# Post-ERG Setup Guide
|
||||||
|
|
||||||
|
Complete setup guide for development and production deployment.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- PHP 8.4
|
||||||
|
- SQLite3 (`php8.4-sqlite3`)
|
||||||
|
- nginx (production)
|
||||||
|
|
||||||
|
## Development Setup
|
||||||
|
|
||||||
|
### 1. Initial Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just setup
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Start Development Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just serve
|
||||||
|
```
|
||||||
|
|
||||||
|
Access at: http://localhost:8000
|
||||||
|
|
||||||
|
### 3. Run Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
### First-Time Server Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
sudo mkdir -p /var/www/posterg
|
||||||
|
sudo chown www-data:posterg /var/www/posterg
|
||||||
|
sudo chmod 775 /var/www/posterg
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just deploy
|
||||||
|
just deploy-nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Admin Password
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just manage-admin-users
|
||||||
|
ssh posterg "sudo bash /tmp/manage-admin-users.sh"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test public site
|
||||||
|
curl -I https://posterg.erg.be/
|
||||||
|
|
||||||
|
# Test admin protection
|
||||||
|
curl -I https://posterg.erg.be/admin/
|
||||||
|
|
||||||
|
# Test file protection
|
||||||
|
curl -I https://posterg.erg.be/storage/test.db
|
||||||
|
```
|
||||||
|
|
||||||
|
## Nginx Configuration
|
||||||
|
|
||||||
|
See `nginx/SETUP.md` and `nginx/docs/PRODUCTION_DEPLOYMENT.md` for detailed nginx setup.
|
||||||
|
|
||||||
|
## Admin Panel
|
||||||
|
|
||||||
|
The admin panel is protected by:
|
||||||
|
1. nginx HTTP Basic Authentication (htpasswd)
|
||||||
|
2. PHP session authentication
|
||||||
|
|
||||||
|
Manage users with:
|
||||||
|
```bash
|
||||||
|
just manage-admin-users
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
### Initialize Test Database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just init-db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reset Database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just reset-db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Test Database to Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just deploy-db
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Operations
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop Development Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just stop
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Migrations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- Admin panel: HTTP Basic Auth + PHP session
|
||||||
|
- File uploads: Stored outside webroot, served via `media.php`
|
||||||
|
- Rate limiting: 30 req/min general, 10 req/min admin
|
||||||
|
- Security headers: X-Frame-Options, CSP, HSTS, etc.
|
||||||
|
|
||||||
|
See `nginx/docs/SECURITY_HEADERS.md` for details.
|
||||||
13
TODO.md
13
TODO.md
@@ -1,4 +1,9 @@
|
|||||||
# TODO
|
- [x] Analyze nginx/docs and nginx/scripts for deduplication opportunities
|
||||||
|
- [x] Deduplicate nginx documentation files (removed DEPLOYMENT_COMPLETE.md, DEPLOY_NOW.md)
|
||||||
- [x] Remove random HSL gradients from homepage cards and use header's background gradient
|
- [x] Remove duplicate scripts (deploy-production.sh, deploy-production-new.sh, manage-admin-users.sh)
|
||||||
- [ ] Review other gradient usages (check if any leftover random hue generation anywhere)
|
- [x] Update justfile with new script paths
|
||||||
|
- [x] Update top-level README.md
|
||||||
|
- [x] Update nginx/README.md
|
||||||
|
- [x] Create nginx/SETUP.md
|
||||||
|
- [x] Create top-level SETUP.md
|
||||||
|
- [x] Update documentation paths (/var/www/html/ → /var/www/posterg/, /formulaire/ → /admin/)
|
||||||
|
|||||||
10
justfile
10
justfile
@@ -62,6 +62,15 @@ setup-server:
|
|||||||
@echo " sudo DEPLOY_USER=\$USER bash /tmp/setup-server.sh"
|
@echo " sudo DEPLOY_USER=\$USER bash /tmp/setup-server.sh"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
||||||
|
[group('deploy')]
|
||||||
|
manage-admin-users:
|
||||||
|
rsync -v scripts/manage-admin-users.sh posterg:/tmp/manage-admin-users.sh
|
||||||
|
@echo ""
|
||||||
|
@echo "Script uploaded. SSH into the server and run:"
|
||||||
|
@echo ""
|
||||||
|
@echo " sudo bash /tmp/manage-admin-users.sh"
|
||||||
|
@echo ""
|
||||||
|
|
||||||
[group('deploy')]
|
[group('deploy')]
|
||||||
deploy-nginx:
|
deploy-nginx:
|
||||||
rsync -v nginx/posterg.conf posterg:/tmp/posterg.conf
|
rsync -v nginx/posterg.conf posterg:/tmp/posterg.conf
|
||||||
@@ -70,6 +79,7 @@ deploy-nginx:
|
|||||||
@echo "Files uploaded. SSH into the server and run:"
|
@echo "Files uploaded. SSH into the server and run:"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo " sudo bash /tmp/deploy-server.sh"
|
@echo " sudo bash /tmp/deploy-server.sh"
|
||||||
|
@echo " sudo systemctl reload nginx"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
|
||||||
[group('deploy')]
|
[group('deploy')]
|
||||||
|
|||||||
@@ -1,379 +0,0 @@
|
|||||||
# ✅ 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 | /storage/ → 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:**
|
|
||||||
```bash
|
|
||||||
# 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:**
|
|
||||||
- `/storage/` - Database files (403)
|
|
||||||
- `/shared/` - PHP libraries (403)
|
|
||||||
- `/data/` - Upload directories (403)
|
|
||||||
- `*.db` files - 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
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 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
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 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:
|
|
||||||
1. ✅ Copy files to server
|
|
||||||
2. ✅ Fix PHP include paths
|
|
||||||
3. ✅ Set correct permissions
|
|
||||||
4. ✅ Test nginx configuration
|
|
||||||
5. ✅ Reload services
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 Testing & Verification
|
|
||||||
|
|
||||||
### Automated Tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 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/storage/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
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# From your local machine
|
|
||||||
curl -I https://posterg.erg.be/ # Should: 200 OK
|
|
||||||
curl -I https://posterg.erg.be/formulaire/ # Should: 401
|
|
||||||
```
|
|
||||||
|
|
||||||
### Browser Tests
|
|
||||||
|
|
||||||
1. ✅ Visit https://posterg.erg.be/ - Homepage loads
|
|
||||||
2. ✅ Search functionality works
|
|
||||||
3. ✅ Individual thesis pages work
|
|
||||||
4. ✅ Admin requires password: https://posterg.erg.be/formulaire/
|
|
||||||
5. ✅ Can upload files in admin (after login)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Monitoring
|
|
||||||
|
|
||||||
### Log Files
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 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
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 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
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg test_posterg_22@
|
|
||||||
```
|
|
||||||
|
|
||||||
### Add Additional Admin Users
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg newusername
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Maintenance
|
|
||||||
|
|
||||||
### Update Website Content
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# From local machine
|
|
||||||
just deploy
|
|
||||||
|
|
||||||
# Content is automatically updated on server
|
|
||||||
```
|
|
||||||
|
|
||||||
### Reload Nginx (after config changes)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo nginx -t # Test configuration
|
|
||||||
sudo systemctl reload nginx # Reload if test passes
|
|
||||||
```
|
|
||||||
|
|
||||||
### Restart PHP-FPM (if needed)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
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:**
|
|
||||||
```bash
|
|
||||||
ls -la /var/www/html/index.php
|
|
||||||
# Should show: -rw-r----- theophile posterg
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check nginx user:**
|
|
||||||
```bash
|
|
||||||
groups www-data
|
|
||||||
# Should show: www-data posterg
|
|
||||||
```
|
|
||||||
|
|
||||||
### Site Returns 500 Internal Server Error
|
|
||||||
|
|
||||||
**Check PHP errors:**
|
|
||||||
```bash
|
|
||||||
tail -f /var/log/nginx/posterg_error.log
|
|
||||||
tail -f /var/www/html/error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check PHP-FPM:**
|
|
||||||
```bash
|
|
||||||
sudo systemctl status php8.4-fpm
|
|
||||||
sudo systemctl restart php8.4-fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
### Admin Panel Not Working
|
|
||||||
|
|
||||||
**Check password file:**
|
|
||||||
```bash
|
|
||||||
ls -la /etc/nginx/.htpasswd-posterg
|
|
||||||
```
|
|
||||||
|
|
||||||
**Reset password:**
|
|
||||||
```bash
|
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg test_posterg_22@
|
|
||||||
```
|
|
||||||
|
|
||||||
### After Deploying, Site Broken
|
|
||||||
|
|
||||||
**Check if paths were fixed:**
|
|
||||||
```bash
|
|
||||||
grep "require_once" /var/www/html/index.php
|
|
||||||
# Should show: __DIR__ . '/shared/Database.php'
|
|
||||||
# NOT: __DIR__ . '/../../shared/Database.php'
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manually fix if needed:**
|
|
||||||
```bash
|
|
||||||
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/storage/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 configuration
|
|
||||||
- `deploy-production.sh` - Automated deployment script
|
|
||||||
- `PRODUCTION_DEPLOYMENT.md` - Detailed deployment guide
|
|
||||||
- `DEPLOY_NOW.md` - Quick deployment instructions
|
|
||||||
- `DEPLOYMENT_COMPLETE.md` - This file
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Deployment completed successfully on February 5, 2026** 🎉
|
|
||||||
@@ -1,276 +0,0 @@
|
|||||||
# 🚀 Deploy Production Nginx Configuration
|
|
||||||
|
|
||||||
Quick guide to fix the current 403 Forbidden errors and deploy production-ready nginx setup.
|
|
||||||
|
|
||||||
## Current Issue
|
|
||||||
|
|
||||||
The site returns **403 Forbidden** because:
|
|
||||||
- Files are owned by `theophile:theophile`
|
|
||||||
- Nginx runs as `www-data` (member of `posterg` group)
|
|
||||||
- Files have `640` permissions but wrong group
|
|
||||||
- Nginx can't read the files
|
|
||||||
|
|
||||||
## Solution
|
|
||||||
|
|
||||||
Deploy the production configuration which will:
|
|
||||||
1. ✅ Fix file permissions (change group to `posterg`)
|
|
||||||
2. ✅ Add security hardening (rate limiting, file blocking)
|
|
||||||
3. ✅ Set up admin password protection
|
|
||||||
4. ✅ Configure proper PHP handling
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Quick Deploy (2 steps)
|
|
||||||
|
|
||||||
### Step 1: Upload to Server
|
|
||||||
|
|
||||||
From your local machine:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
just deploy-nginx-production
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 2: Run on Server
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo bash /tmp/deploy-production.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
That's it! The site should work after this.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 What the Script Does
|
|
||||||
|
|
||||||
The deployment script will:
|
|
||||||
|
|
||||||
1. **Fix Permissions**
|
|
||||||
- Change ownership: `theophile:posterg` (so www-data can read)
|
|
||||||
- Directories: `755` (readable by all)
|
|
||||||
- Files: `640` (readable by owner and group)
|
|
||||||
- Upload dirs: `775` (writable by group)
|
|
||||||
|
|
||||||
2. **Setup Admin Password**
|
|
||||||
- Creates `/etc/nginx/.htpasswd-posterg` if missing
|
|
||||||
- Prompts for username and password
|
|
||||||
|
|
||||||
3. **Install Nginx Config**
|
|
||||||
- Backs up existing config
|
|
||||||
- Installs production config
|
|
||||||
- Creates symlink in sites-enabled
|
|
||||||
- Removes default site
|
|
||||||
|
|
||||||
4. **Test & Reload**
|
|
||||||
- Tests nginx configuration
|
|
||||||
- Reloads nginx if valid
|
|
||||||
- Verifies PHP-FPM is running
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔒 Security Features Added
|
|
||||||
|
|
||||||
The new configuration adds:
|
|
||||||
|
|
||||||
✅ **Rate Limiting**
|
|
||||||
- General: 30 requests/minute
|
|
||||||
- Search: 30 requests/minute
|
|
||||||
- Admin: 10 requests/minute
|
|
||||||
|
|
||||||
✅ **File Protection**
|
|
||||||
- Database files (`.db`) → 403 Forbidden
|
|
||||||
- Sensitive files (`.md`, `.sql`, `.txt`) → 403 Forbidden
|
|
||||||
- `/storage/` directory → 403 Forbidden
|
|
||||||
- `/shared/` directory → 403 Forbidden
|
|
||||||
- `/data/` directory → 403 Forbidden
|
|
||||||
- Hidden files (`.git`, `.env`) → 403 Forbidden
|
|
||||||
|
|
||||||
✅ **Admin Panel Protection**
|
|
||||||
- `/formulaire/` requires HTTP Basic Authentication
|
|
||||||
- Rate limited to 10 requests/minute
|
|
||||||
- Hidden from search engines
|
|
||||||
|
|
||||||
✅ **Security Headers**
|
|
||||||
- X-Frame-Options (clickjacking protection)
|
|
||||||
- X-Content-Type-Options (MIME sniffing protection)
|
|
||||||
- X-XSS-Protection
|
|
||||||
- Referrer-Policy
|
|
||||||
- Permissions-Policy
|
|
||||||
|
|
||||||
✅ **File Upload**
|
|
||||||
- Max size: 100MB
|
|
||||||
- Timeouts: 120 seconds
|
|
||||||
- Upload directories writable by www-data
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 Testing After Deployment
|
|
||||||
|
|
||||||
On the server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Should return 200 OK now
|
|
||||||
curl -I http://localhost/
|
|
||||||
|
|
||||||
# Should return HTML content
|
|
||||||
curl http://localhost/index.php | head -n 20
|
|
||||||
|
|
||||||
# Admin should ask for password (401)
|
|
||||||
curl -I http://localhost/formulaire/
|
|
||||||
|
|
||||||
# Database should be blocked (403)
|
|
||||||
curl -I http://localhost/storage/posterg.db
|
|
||||||
|
|
||||||
# Sensitive files should be blocked (403)
|
|
||||||
curl -I http://localhost/README.md
|
|
||||||
curl -I http://localhost/shared/Database.php
|
|
||||||
```
|
|
||||||
|
|
||||||
From your browser:
|
|
||||||
- Visit https://posterg.erg.be/ → Should work!
|
|
||||||
- Visit https://posterg.erg.be/formulaire/ → Should ask for password
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Manual Steps (If Script Fails)
|
|
||||||
|
|
||||||
If the automated script fails, here's the manual process:
|
|
||||||
|
|
||||||
### Fix Permissions
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo chown -R theophile:posterg /var/www/html/
|
|
||||||
sudo find /var/www/html -type d -exec chmod 755 {} \;
|
|
||||||
sudo find /var/www/html -type f -exec chmod 640 {} \;
|
|
||||||
sudo chmod 775 /var/www/html/formulaire/data/theses
|
|
||||||
sudo chmod 775 /var/www/html/formulaire/data/covers
|
|
||||||
```
|
|
||||||
|
|
||||||
### Install Config
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# On server
|
|
||||||
sudo cp /tmp/posterg.conf /etc/nginx/sites-available/posterg
|
|
||||||
sudo ln -sf /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/posterg
|
|
||||||
sudo rm -f /etc/nginx/sites-enabled/default
|
|
||||||
sudo nginx -t
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### Setup Admin Password
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo htpasswd -c /etc/nginx/.htpasswd-posterg admin
|
|
||||||
# Enter password when prompted
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🆘 Troubleshooting
|
|
||||||
|
|
||||||
### Still Getting 403 Forbidden
|
|
||||||
|
|
||||||
**Check file ownership:**
|
|
||||||
```bash
|
|
||||||
ls -la /var/www/html/index.php
|
|
||||||
# Should show: -rw-r----- theophile posterg
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check nginx user is in posterg group:**
|
|
||||||
```bash
|
|
||||||
groups www-data
|
|
||||||
# Should show: www-data : www-data posterg
|
|
||||||
```
|
|
||||||
|
|
||||||
### Can't Access Admin Panel
|
|
||||||
|
|
||||||
**Verify password file:**
|
|
||||||
```bash
|
|
||||||
ls -la /etc/nginx/.htpasswd-posterg
|
|
||||||
# Should exist and be readable
|
|
||||||
```
|
|
||||||
|
|
||||||
**Test with credentials:**
|
|
||||||
```bash
|
|
||||||
curl -u admin:your_password http://localhost/formulaire/
|
|
||||||
```
|
|
||||||
|
|
||||||
### PHP Not Working (500 Error)
|
|
||||||
|
|
||||||
**Check PHP-FPM:**
|
|
||||||
```bash
|
|
||||||
sudo systemctl status php8.4-fpm
|
|
||||||
sudo systemctl restart php8.4-fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check socket:**
|
|
||||||
```bash
|
|
||||||
ls -la /var/run/php/php8.4-fpm.sock
|
|
||||||
# Should exist
|
|
||||||
```
|
|
||||||
|
|
||||||
### View Error Logs
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Nginx errors
|
|
||||||
sudo tail -f /var/log/nginx/posterg_error.log
|
|
||||||
|
|
||||||
# PHP errors
|
|
||||||
sudo tail -f /var/www/html/error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Current vs Production Config
|
|
||||||
|
|
||||||
| Feature | Current (Default) | Production |
|
|
||||||
|---------|------------------|------------|
|
|
||||||
| PHP Version | ✅ 8.4 | ✅ 8.4 |
|
|
||||||
| File Protection | ❌ None | ✅ Comprehensive |
|
|
||||||
| Rate Limiting | ❌ None | ✅ Yes |
|
|
||||||
| Admin Password | ❌ None | ✅ Yes |
|
|
||||||
| Security Headers | ❌ None | ✅ Yes |
|
|
||||||
| Upload Size | ⚠️ Default (2MB) | ✅ 100MB |
|
|
||||||
| Logging | ⚠️ Generic | ✅ Separate logs |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Success Checklist
|
|
||||||
|
|
||||||
After deployment, verify:
|
|
||||||
|
|
||||||
- [ ] Public site loads: https://posterg.erg.be/
|
|
||||||
- [ ] Admin requires password: https://posterg.erg.be/formulaire/
|
|
||||||
- [ ] Search works
|
|
||||||
- [ ] Individual thesis pages work
|
|
||||||
- [ ] Database is protected (403)
|
|
||||||
- [ ] Sensitive files blocked (403)
|
|
||||||
- [ ] No errors in logs
|
|
||||||
- [ ] File uploads work (in admin)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📞 Need Help?
|
|
||||||
|
|
||||||
1. **Check logs first:**
|
|
||||||
```bash
|
|
||||||
sudo tail -50 /var/log/nginx/posterg_error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Test nginx config:**
|
|
||||||
```bash
|
|
||||||
sudo nginx -t
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Restart services:**
|
|
||||||
```bash
|
|
||||||
sudo systemctl restart php8.4-fpm
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Check service status:**
|
|
||||||
```bash
|
|
||||||
sudo systemctl status nginx
|
|
||||||
sudo systemctl status php8.4-fpm
|
|
||||||
```
|
|
||||||
@@ -1,346 +0,0 @@
|
|||||||
# Production Deployment Guide - Post-ERG
|
|
||||||
|
|
||||||
This guide will help you deploy the production nginx configuration with proper security and permissions.
|
|
||||||
|
|
||||||
## 🎯 Overview
|
|
||||||
|
|
||||||
Your current setup:
|
|
||||||
- **Server IP**: 192.168.6.125 (internal)
|
|
||||||
- **PHP Version**: 8.4
|
|
||||||
- **SSL/TLS**: Handled by reverse proxy (already working)
|
|
||||||
- **Issue**: File permissions preventing nginx from reading files
|
|
||||||
|
|
||||||
## 🚀 Quick Deployment
|
|
||||||
|
|
||||||
From your local machine:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Deploy the production config and deployment script
|
|
||||||
just deploy-nginx-production
|
|
||||||
|
|
||||||
# SSH to the server and run the deployment
|
|
||||||
ssh posterg
|
|
||||||
sudo /tmp/deploy-production.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📋 Step-by-Step Deployment
|
|
||||||
|
|
||||||
### 1. Set Up Admin Password (First Time Only)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo htpasswd -c /etc/nginx/.htpasswd-posterg admin
|
|
||||||
# Enter a strong password when prompted
|
|
||||||
```
|
|
||||||
|
|
||||||
**💡 Tip**: Generate a strong password:
|
|
||||||
```bash
|
|
||||||
openssl rand -base64 32
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Deploy Configuration
|
|
||||||
|
|
||||||
From your local machine:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Upload nginx config and deployment script
|
|
||||||
rsync -vur ./nginx/posterg-production.conf posterg:/tmp/posterg.conf
|
|
||||||
rsync -vur ./nginx/deploy-production.sh posterg:/tmp/deploy-production.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Run Deployment Script
|
|
||||||
|
|
||||||
On the server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo chmod +x /tmp/deploy-production.sh
|
|
||||||
sudo /tmp/deploy-production.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
The script will:
|
|
||||||
- ✅ Fix file permissions (set to posterg group)
|
|
||||||
- ✅ Install nginx configuration
|
|
||||||
- ✅ Test nginx configuration
|
|
||||||
- ✅ Reload nginx
|
|
||||||
- ✅ Check PHP-FPM status
|
|
||||||
|
|
||||||
## 🔧 Manual Deployment (Alternative)
|
|
||||||
|
|
||||||
If you prefer to do it manually:
|
|
||||||
|
|
||||||
### Step 1: Fix Permissions
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
|
|
||||||
# Set correct ownership (posterg group)
|
|
||||||
sudo chown -R theophile:posterg /var/www/html/
|
|
||||||
|
|
||||||
# Set directory permissions
|
|
||||||
sudo find /var/www/html -type d -exec chmod 755 {} \;
|
|
||||||
|
|
||||||
# Set file permissions (group readable)
|
|
||||||
sudo find /var/www/html -type f -exec chmod 640 {} \;
|
|
||||||
|
|
||||||
# Make upload directories writable
|
|
||||||
sudo chmod 775 /var/www/html/formulaire/data/theses
|
|
||||||
sudo chmod 775 /var/www/html/formulaire/data/covers
|
|
||||||
|
|
||||||
# Protect database
|
|
||||||
sudo chmod 640 /var/www/html/storage/posterg.db
|
|
||||||
sudo chown www-data:posterg /var/www/html/storage/posterg.db
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 2: Deploy Nginx Config
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Copy config
|
|
||||||
sudo cp /tmp/posterg.conf /etc/nginx/sites-available/posterg
|
|
||||||
|
|
||||||
# Enable site
|
|
||||||
sudo ln -sf /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/posterg
|
|
||||||
|
|
||||||
# Disable default site
|
|
||||||
sudo rm -f /etc/nginx/sites-enabled/default
|
|
||||||
|
|
||||||
# Test configuration
|
|
||||||
sudo nginx -t
|
|
||||||
|
|
||||||
# Reload nginx
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 3: Verify PHP-FPM
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check PHP-FPM is running
|
|
||||||
sudo systemctl status php8.4-fpm
|
|
||||||
|
|
||||||
# If not running, start it
|
|
||||||
sudo systemctl start php8.4-fpm
|
|
||||||
sudo systemctl enable php8.4-fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🧪 Testing
|
|
||||||
|
|
||||||
### Test Public Site
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Should return 200 OK
|
|
||||||
curl -I http://localhost/
|
|
||||||
|
|
||||||
# Should return 200 OK with HTML
|
|
||||||
curl http://localhost/index.php
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Admin Protection
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Should return 401 Unauthorized
|
|
||||||
curl -I http://localhost/formulaire/
|
|
||||||
|
|
||||||
# Should return 200 OK with credentials
|
|
||||||
curl -u admin:your_password http://localhost/formulaire/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test File Protection
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# These should all return 403 Forbidden
|
|
||||||
curl -I http://localhost/storage/posterg.db
|
|
||||||
curl -I http://localhost/README.md
|
|
||||||
curl -I http://localhost/shared/Database.php
|
|
||||||
curl -I http://localhost/.git/config
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Security Headers
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -I http://localhost/ | grep -E "X-Frame|X-Content|X-XSS"
|
|
||||||
```
|
|
||||||
|
|
||||||
### From Your Browser
|
|
||||||
|
|
||||||
Visit https://posterg.erg.be/ - should work now!
|
|
||||||
|
|
||||||
## 🔍 Troubleshooting
|
|
||||||
|
|
||||||
### Still Getting 403 Forbidden
|
|
||||||
|
|
||||||
**Check file permissions:**
|
|
||||||
```bash
|
|
||||||
ls -la /var/www/html/index.php
|
|
||||||
# Should show: -rw-r----- 1 theophile posterg ...
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check nginx user is in posterg group:**
|
|
||||||
```bash
|
|
||||||
groups www-data
|
|
||||||
# Should show: www-data : www-data posterg
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check directory permissions:**
|
|
||||||
```bash
|
|
||||||
ls -lad /var/www/html
|
|
||||||
# Should show: drwxr-xr-x ... posterg
|
|
||||||
```
|
|
||||||
|
|
||||||
### 502 Bad Gateway
|
|
||||||
|
|
||||||
**Check PHP-FPM:**
|
|
||||||
```bash
|
|
||||||
sudo systemctl status php8.4-fpm
|
|
||||||
sudo systemctl restart php8.4-fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check socket file:**
|
|
||||||
```bash
|
|
||||||
ls -la /var/run/php/php8.4-fpm.sock
|
|
||||||
# Should exist and be writable by www-data
|
|
||||||
```
|
|
||||||
|
|
||||||
### Admin Password Not Working
|
|
||||||
|
|
||||||
**Reset password:**
|
|
||||||
```bash
|
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg admin
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check file exists:**
|
|
||||||
```bash
|
|
||||||
ls -la /etc/nginx/.htpasswd-posterg
|
|
||||||
# Should show: -rw-r--r-- 1 root root ...
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database Not Accessible to PHP
|
|
||||||
|
|
||||||
**Fix database permissions:**
|
|
||||||
```bash
|
|
||||||
sudo chown www-data:posterg /var/www/html/storage/posterg.db
|
|
||||||
sudo chmod 640 /var/www/html/storage/posterg.db
|
|
||||||
sudo chmod 755 /var/www/html/storage/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Can't Write Uploaded Files
|
|
||||||
|
|
||||||
**Fix upload directory permissions:**
|
|
||||||
```bash
|
|
||||||
sudo chmod 775 /var/www/html/formulaire/data/theses
|
|
||||||
sudo chmod 775 /var/www/html/formulaire/data/covers
|
|
||||||
sudo chown -R theophile:posterg /var/www/html/formulaire/data/
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 Monitoring
|
|
||||||
|
|
||||||
### Watch Logs
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Access logs
|
|
||||||
sudo tail -f /var/log/nginx/posterg_access.log
|
|
||||||
|
|
||||||
# Error logs
|
|
||||||
sudo tail -f /var/log/nginx/posterg_error.log
|
|
||||||
|
|
||||||
# PHP errors
|
|
||||||
sudo tail -f /var/log/php8.4-fpm.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check Nginx Status
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl status nginx
|
|
||||||
sudo nginx -t
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check Resource Usage
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Nginx processes
|
|
||||||
ps aux | grep nginx
|
|
||||||
|
|
||||||
# PHP-FPM processes
|
|
||||||
ps aux | grep php-fpm
|
|
||||||
|
|
||||||
# Disk usage
|
|
||||||
df -h /var/www/html
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔒 Security Checklist
|
|
||||||
|
|
||||||
After deployment, verify:
|
|
||||||
|
|
||||||
- [ ] ✅ Public site accessible at https://posterg.erg.be/
|
|
||||||
- [ ] ✅ Admin panel requires password
|
|
||||||
- [ ] ✅ Database files return 403 Forbidden
|
|
||||||
- [ ] ✅ Sensitive files (.md, .sql) return 403 Forbidden
|
|
||||||
- [ ] ✅ Shared directory returns 403 Forbidden
|
|
||||||
- [ ] ✅ Security headers present in responses
|
|
||||||
- [ ] ✅ PHP-FPM running and accessible
|
|
||||||
- [ ] ✅ File uploads work in admin panel
|
|
||||||
- [ ] ✅ Search functionality works
|
|
||||||
- [ ] ✅ Logs are being written
|
|
||||||
|
|
||||||
## 🔄 Updating the Site
|
|
||||||
|
|
||||||
For future updates:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Deploy code changes
|
|
||||||
just deploy
|
|
||||||
|
|
||||||
# Reload nginx if config changed
|
|
||||||
ssh posterg "sudo systemctl reload nginx"
|
|
||||||
|
|
||||||
# Clear PHP opcache if needed
|
|
||||||
ssh posterg "sudo systemctl reload php8.4-fpm"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🆘 Emergency Recovery
|
|
||||||
|
|
||||||
If something goes wrong:
|
|
||||||
|
|
||||||
### Restore Default Config
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo rm /etc/nginx/sites-enabled/posterg
|
|
||||||
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### Reset Permissions
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo chown -R www-data:www-data /var/www/html
|
|
||||||
sudo find /var/www/html -type d -exec chmod 755 {} \;
|
|
||||||
sudo find /var/www/html -type f -exec chmod 644 {} \;
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📞 Support Resources
|
|
||||||
|
|
||||||
- **Nginx docs**: https://nginx.org/en/docs/
|
|
||||||
- **PHP-FPM docs**: https://www.php.net/manual/en/install.fpm.php
|
|
||||||
- **Let's Encrypt**: https://letsencrypt.org/
|
|
||||||
- **Security headers**: https://securityheaders.com/
|
|
||||||
|
|
||||||
## 🎉 Success Criteria
|
|
||||||
|
|
||||||
You know the deployment is successful when:
|
|
||||||
|
|
||||||
1. ✅ Visit https://posterg.erg.be/ - shows homepage
|
|
||||||
2. ✅ Visit https://posterg.erg.be/formulaire/ - asks for password
|
|
||||||
3. ✅ Search works correctly
|
|
||||||
4. ✅ Individual thesis pages load
|
|
||||||
5. ✅ Admin can upload files
|
|
||||||
6. ✅ No 403 or 502 errors in logs
|
|
||||||
7. ✅ Security headers present (check with curl -I)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Need help?** Check the error logs first:
|
|
||||||
```bash
|
|
||||||
sudo tail -f /var/log/nginx/posterg_error.log
|
|
||||||
```
|
|
||||||
117
nginx/README.md
117
nginx/README.md
@@ -1,17 +1,26 @@
|
|||||||
# Nginx Configuration - Post-ERG
|
# Nginx Configuration - Post-ERG
|
||||||
|
|
||||||
This directory contains nginx configuration and setup scripts for the Post-ERG thesis website.
|
This directory contains nginx configuration and documentation for the Post-ERG thesis website.
|
||||||
|
|
||||||
## 📁 Files
|
## 📁 Files
|
||||||
|
|
||||||
- **`posterg.conf`** - Complete nginx configuration file
|
- **`posterg.conf`** - Complete nginx configuration file
|
||||||
- **`setup-password.sh`** - Script to create admin passwords
|
- **`scripts/`** - Server setup scripts
|
||||||
- **`SETUP.md`** - Detailed setup instructions
|
- `setup-password.sh` - Create admin passwords
|
||||||
- **`QUICK_REFERENCE.md`** - Command reference and troubleshooting
|
- `install-php-sqlite.sh` - Install PHP SQLite extension
|
||||||
|
- `fix-paths.sh` - Fix PHP include paths
|
||||||
|
- **`docs/`** - Documentation
|
||||||
|
- `PRODUCTION_DEPLOYMENT.md` - Deployment guide
|
||||||
|
- `QUICK_REFERENCE.md` - Command reference
|
||||||
|
- `ADMIN_USERS.md` - User management
|
||||||
|
- `SECURITY_HEADERS.md` - Security headers reference
|
||||||
|
- `PHP_AUTH_LAYER.md` - Authentication layer documentation
|
||||||
|
- `HTACCESS_TO_ NGINX.md` - Apache to nginx migration notes
|
||||||
|
- `TEST_DATABASE_SETUP.md` - Test database deployment
|
||||||
|
|
||||||
## 🚀 Quick Start
|
## 🚀 Quick Start
|
||||||
|
|
||||||
### 1. Deploy nginx configuration (automated)
|
### Deploy nginx configuration
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# From your local machine
|
# From your local machine
|
||||||
@@ -19,38 +28,37 @@ just deploy-nginx
|
|||||||
|
|
||||||
# Then on the server:
|
# Then on the server:
|
||||||
ssh posterg
|
ssh posterg
|
||||||
sudo bash /tmp/deploy-production.sh
|
sudo bash /tmp/deploy-server.sh
|
||||||
|
sudo systemctl reload nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
The deployment script will:
|
The deployment script will:
|
||||||
- ✅ Fix file permissions (posterg group)
|
- ✅ Fix file permissions (www-data:posterg)
|
||||||
- ✅ Set up admin password (if needed)
|
|
||||||
- ✅ Install nginx configuration
|
- ✅ Install nginx configuration
|
||||||
- ✅ Test and reload nginx
|
- ✅ Test and reload nginx
|
||||||
- ✅ Verify PHP-FPM is running
|
- ✅ Verify PHP-FPM is running
|
||||||
|
|
||||||
### 2. SSL/TLS
|
### Manage admin users
|
||||||
|
|
||||||
SSL/TLS is handled by the upstream reverse proxy and is already working.
|
```bash
|
||||||
No additional SSL setup is needed on this server.
|
just manage-admin-users
|
||||||
|
ssh posterg "sudo bash /tmp/manage-admin-users.sh"
|
||||||
|
```
|
||||||
|
|
||||||
## 🔒 Security Features
|
## 🔒 Security Features
|
||||||
|
|
||||||
### Admin Panel Protection
|
### Admin Panel Protection
|
||||||
- **Password required** for `/formulaire/` (admin panel)
|
- **Password required** for `/admin/`
|
||||||
- HTTP Basic Authentication
|
- HTTP Basic Authentication
|
||||||
- Rate limited: 10 requests/minute
|
- Rate limited: 10 requests/minute
|
||||||
|
|
||||||
### File Access Protection
|
### File Access Protection
|
||||||
- Database files (`.db`) - **BLOCKED**
|
- Database files (`.db`) - **BLOCKED**
|
||||||
- Sensitive files (`.md`, `.sql`, `.env`) - **BLOCKED**
|
- Sensitive files (`.md`, `.sql`, `.env`) - **BLOCKED**
|
||||||
- `/src` directory (PHP source) - **BLOCKED**
|
- `/src` directory - **BLOCKED**
|
||||||
- `/templates` directory (PHP templates) - **BLOCKED**
|
- `/templates` directory - **BLOCKED**
|
||||||
- `/config` directory (configuration) - **BLOCKED**
|
- `/config` directory - **BLOCKED**
|
||||||
- `/storage` directory (databases) - **BLOCKED**
|
- `/storage` directory - **BLOCKED**
|
||||||
- `/tests` directory - **BLOCKED**
|
|
||||||
- `/scripts` directory - **BLOCKED**
|
|
||||||
- `/docs` directory - **BLOCKED**
|
|
||||||
- Hidden files (`.git`, etc.) - **BLOCKED**
|
- Hidden files (`.git`, etc.) - **BLOCKED**
|
||||||
|
|
||||||
### Rate Limiting
|
### Rate Limiting
|
||||||
@@ -61,45 +69,25 @@ No additional SSL setup is needed on this server.
|
|||||||
### Security Headers
|
### Security Headers
|
||||||
- ✅ X-Frame-Options (clickjacking protection)
|
- ✅ X-Frame-Options (clickjacking protection)
|
||||||
- ✅ X-Content-Type-Options (MIME sniffing protection)
|
- ✅ X-Content-Type-Options (MIME sniffing protection)
|
||||||
- ✅ X-XSS-Protection (XSS filter)
|
|
||||||
- ✅ Strict-Transport-Security (force HTTPS)
|
- ✅ Strict-Transport-Security (force HTTPS)
|
||||||
- ✅ Referrer-Policy (referrer control)
|
- ✅ Referrer-Policy (referrer control)
|
||||||
- ✅ Permissions-Policy (disable browser features)
|
- ✅ Permissions-Policy (disable browser features)
|
||||||
|
|
||||||
### SSL/TLS
|
|
||||||
- TLS 1.2 and 1.3 only
|
|
||||||
- Strong cipher suites
|
|
||||||
- OCSP stapling
|
|
||||||
- HSTS enabled
|
|
||||||
|
|
||||||
## 📚 Documentation
|
## 📚 Documentation
|
||||||
|
|
||||||
- **[SETUP.md](SETUP.md)** - Complete setup guide
|
- **[docs/PRODUCTION_DEPLOYMENT.md](docs/PRODUCTION_DEPLOYMENT.md)** - Complete deployment guide
|
||||||
- Installation steps
|
- **[docs/QUICK_REFERENCE.md](docs/QUICK_REFERENCE.md)** - Command reference and troubleshooting
|
||||||
- Configuration details
|
- **[docs/ADMIN_USERS.md](docs/ADMIN_USERS.md)** - Admin user management
|
||||||
- Testing procedures
|
- **[docs/SECURITY_HEADERS.md](docs/SECURITY_HEADERS.md)** - Security headers reference
|
||||||
- Troubleshooting
|
|
||||||
- Performance tuning
|
|
||||||
- Security checklist
|
|
||||||
|
|
||||||
- **[QUICK_REFERENCE.md](QUICK_REFERENCE.md)** - Command reference
|
|
||||||
- Common operations
|
|
||||||
- Password management
|
|
||||||
- Nginx control
|
|
||||||
- Log viewing
|
|
||||||
- Testing commands
|
|
||||||
- Troubleshooting
|
|
||||||
|
|
||||||
## 🧪 Testing
|
## 🧪 Testing
|
||||||
|
|
||||||
Test your configuration:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Test admin authentication
|
# Test admin authentication
|
||||||
curl -I https://posterg.erg.be/formulaire/
|
curl -I https://posterg.erg.be/admin/
|
||||||
|
|
||||||
# Test file protection
|
# Test file protection
|
||||||
curl -I https://posterg.erg.be/storage/posterg.db
|
curl -I https://posterg.erg.be/storage/test.db
|
||||||
|
|
||||||
# Test security headers
|
# Test security headers
|
||||||
curl -I https://posterg.erg.be/ | grep -E "X-|Strict-Transport"
|
curl -I https://posterg.erg.be/ | grep -E "X-|Strict-Transport"
|
||||||
@@ -109,60 +97,27 @@ curl -I https://posterg.erg.be/ | grep -E "X-|Strict-Transport"
|
|||||||
|
|
||||||
### Admin can't log in
|
### Admin can't log in
|
||||||
```bash
|
```bash
|
||||||
# Reset password
|
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg admin
|
sudo htpasswd /etc/nginx/.htpasswd-posterg admin
|
||||||
```
|
```
|
||||||
|
|
||||||
### 502 Bad Gateway
|
### 502 Bad Gateway
|
||||||
```bash
|
```bash
|
||||||
# Check PHP-FPM
|
sudo systemctl status php8.4-fpm
|
||||||
sudo systemctl status php8.2-fpm
|
sudo systemctl restart php8.4-fpm
|
||||||
sudo systemctl restart php8.2-fpm
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuration errors
|
### Configuration errors
|
||||||
```bash
|
```bash
|
||||||
# Test and show errors
|
|
||||||
sudo nginx -t
|
sudo nginx -t
|
||||||
```
|
```
|
||||||
|
|
||||||
## 📊 Monitoring
|
## 📊 Monitoring
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Watch access logs
|
# Watch logs
|
||||||
sudo tail -f /var/log/nginx/posterg_access.log
|
sudo tail -f /var/log/nginx/posterg_access.log
|
||||||
|
|
||||||
# Watch error logs
|
|
||||||
sudo tail -f /var/log/nginx/posterg_error.log
|
sudo tail -f /var/log/nginx/posterg_error.log
|
||||||
|
|
||||||
# Check nginx status
|
# Check nginx status
|
||||||
sudo systemctl status nginx
|
sudo systemctl status nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🔄 Maintenance
|
|
||||||
|
|
||||||
### Change admin password
|
|
||||||
```bash
|
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg admin
|
|
||||||
```
|
|
||||||
|
|
||||||
### Reload after config changes
|
|
||||||
```bash
|
|
||||||
sudo nginx -t && sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### Renew SSL certificate
|
|
||||||
```bash
|
|
||||||
sudo certbot renew
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📞 Support
|
|
||||||
|
|
||||||
For detailed instructions, see:
|
|
||||||
- **SETUP.md** - Complete setup guide
|
|
||||||
- **QUICK_REFERENCE.md** - Command reference
|
|
||||||
|
|
||||||
For issues:
|
|
||||||
1. Check nginx error logs: `sudo tail /var/log/nginx/posterg_error.log`
|
|
||||||
2. Test configuration: `sudo nginx -t`
|
|
||||||
3. Check PHP-FPM: `sudo systemctl status php8.2-fpm`
|
|
||||||
|
|||||||
360
nginx/SETUP.md
360
nginx/SETUP.md
@@ -1,369 +1,127 @@
|
|||||||
# Nginx Setup for Post-ERG
|
# Nginx Setup for Post-ERG
|
||||||
|
|
||||||
This document explains how to set up nginx with security features and password protection for the admin panel.
|
Complete setup guide for nginx with security features and password protection.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Ubuntu/Debian server with root access
|
- Ubuntu/Debian server with root access
|
||||||
- Nginx installed
|
- Nginx installed
|
||||||
- PHP-FPM installed (PHP 8.2 or later)
|
- PHP-FPM installed (PHP 8.4)
|
||||||
- Domain name pointed to your server
|
- Domain name pointed to your server
|
||||||
|
|
||||||
## Installation Steps
|
## Quick Setup (Recommended)
|
||||||
|
|
||||||
|
### 1. Deploy from your local machine
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just deploy-nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Apply on the server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
sudo bash /tmp/deploy-server.sh
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Set admin password (first time only)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just manage-admin-users
|
||||||
|
ssh posterg "sudo bash /tmp/manage-admin-users.sh"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Manual Setup Steps
|
||||||
|
|
||||||
### 1. Install Required Packages
|
### 1. Install Required Packages
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install nginx and apache2-utils (for htpasswd)
|
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install nginx apache2-utils php8.2-fpm
|
sudo apt install nginx apache2-utils php8.4-fpm
|
||||||
|
|
||||||
# Install SSL certificate tool (optional, for HTTPS)
|
|
||||||
sudo apt install certbot python3-certbot-nginx
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Create Password File for Admin Panel
|
### 2. Create Admin Password
|
||||||
|
|
||||||
Create a password-protected admin area:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create htpasswd file
|
|
||||||
sudo htpasswd -c /etc/nginx/.htpasswd-posterg admin
|
sudo htpasswd -c /etc/nginx/.htpasswd-posterg admin
|
||||||
|
|
||||||
# You'll be prompted to enter a password
|
|
||||||
# Enter a strong password (e.g., generated with: openssl rand -base64 32)
|
|
||||||
|
|
||||||
# Add additional users (without -c flag)
|
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg supervisor
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Important**: Store the username and password securely!
|
|
||||||
|
|
||||||
### 3. Copy Nginx Configuration
|
### 3. Copy Nginx Configuration
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Copy the config file
|
|
||||||
sudo cp nginx/posterg.conf /etc/nginx/sites-available/posterg
|
sudo cp nginx/posterg.conf /etc/nginx/sites-available/posterg
|
||||||
|
|
||||||
# Update PHP-FPM socket path if needed (check your PHP version)
|
|
||||||
# Edit the file and change php8.2-fpm.sock to match your version
|
|
||||||
sudo nano /etc/nginx/sites-available/posterg
|
|
||||||
|
|
||||||
# Create symlink to enable the site
|
|
||||||
sudo ln -s /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/
|
sudo ln -s /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/
|
||||||
|
sudo rm -f /etc/nginx/sites-enabled/default
|
||||||
# Remove default site (optional)
|
|
||||||
sudo rm /etc/nginx/sites-enabled/default
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Update Domain Name
|
### 4. Test and Reload
|
||||||
|
|
||||||
Edit the configuration to use your domain:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo nano /etc/nginx/sites-available/posterg
|
|
||||||
|
|
||||||
# Change these lines:
|
|
||||||
# server_name posterg.erg.be www.posterg.erg.be;
|
|
||||||
# to your actual domain name
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Test and Reload Nginx
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Test configuration
|
|
||||||
sudo nginx -t
|
sudo nginx -t
|
||||||
|
|
||||||
# If test passes, reload nginx
|
|
||||||
sudo systemctl reload nginx
|
sudo systemctl reload nginx
|
||||||
|
|
||||||
# Check nginx status
|
|
||||||
sudo systemctl status nginx
|
sudo systemctl status nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Set Up SSL/HTTPS (Production)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Get SSL certificate from Let's Encrypt
|
|
||||||
sudo certbot --nginx -d posterg.erg.be -d www.posterg.erg.be
|
|
||||||
|
|
||||||
# Follow the prompts
|
|
||||||
# Certbot will automatically update your nginx config
|
|
||||||
|
|
||||||
# Enable auto-renewal
|
|
||||||
sudo systemctl enable certbot.timer
|
|
||||||
sudo systemctl start certbot.timer
|
|
||||||
|
|
||||||
# Test renewal
|
|
||||||
sudo certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Configure PHP-FPM
|
|
||||||
|
|
||||||
Optimize PHP-FPM for security and performance:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
Update these settings:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
# Security
|
|
||||||
php_admin_value[open_basedir] = /var/www/html:/tmp
|
|
||||||
php_admin_flag[allow_url_fopen] = off
|
|
||||||
|
|
||||||
# Performance
|
|
||||||
pm = dynamic
|
|
||||||
pm.max_children = 50
|
|
||||||
pm.start_servers = 5
|
|
||||||
pm.min_spare_servers = 5
|
|
||||||
pm.max_spare_servers = 35
|
|
||||||
|
|
||||||
# Uploads
|
|
||||||
php_value[upload_max_filesize] = 50M
|
|
||||||
php_value[post_max_size] = 100M
|
|
||||||
php_value[max_execution_time] = 120
|
|
||||||
php_value[max_input_time] = 120
|
|
||||||
```
|
|
||||||
|
|
||||||
Restart PHP-FPM:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo systemctl restart php8.2-fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Set Correct Permissions
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Set ownership
|
|
||||||
sudo chown -R www-data:www-data /var/www/html
|
|
||||||
|
|
||||||
# Set directory permissions
|
|
||||||
sudo find /var/www/html -type d -exec chmod 755 {} \;
|
|
||||||
|
|
||||||
# Set file permissions
|
|
||||||
sudo find /var/www/html -type f -exec chmod 644 {} \;
|
|
||||||
|
|
||||||
# Make upload directories writable
|
|
||||||
sudo chmod 775 /var/www/html/formulaire/data/theses
|
|
||||||
sudo chmod 775 /var/www/html/formulaire/data/covers
|
|
||||||
|
|
||||||
# Protect database
|
|
||||||
sudo chmod 600 /var/www/html/storage/posterg.db
|
|
||||||
sudo chown www-data:www-data /var/www/html/storage/posterg.db
|
|
||||||
```
|
|
||||||
|
|
||||||
## Security Features Implemented
|
|
||||||
|
|
||||||
### 1. **Admin Panel Password Protection**
|
|
||||||
- HTTP Basic Authentication on `/formulaire/` path
|
|
||||||
- Only authorized users can access admin panel
|
|
||||||
|
|
||||||
### 2. **Rate Limiting**
|
|
||||||
- General requests: 30 requests/minute
|
|
||||||
- Search endpoint: 30 requests/minute
|
|
||||||
- Admin panel: 10 requests/minute
|
|
||||||
|
|
||||||
### 3. **File Access Protection**
|
|
||||||
- `.db` files blocked
|
|
||||||
- `.md`, `.txt`, `.sql` files blocked
|
|
||||||
- `shared/` directory blocked (PHP includes only)
|
|
||||||
- `tests/` directory blocked
|
|
||||||
- `cache/` directory blocked
|
|
||||||
- Hidden files (`.git`, `.env`) blocked
|
|
||||||
|
|
||||||
### 4. **Security Headers**
|
|
||||||
- `X-Frame-Options`: Prevent clickjacking
|
|
||||||
- `X-Content-Type-Options`: Prevent MIME sniffing
|
|
||||||
- `X-XSS-Protection`: Enable XSS filter
|
|
||||||
- `Strict-Transport-Security`: Force HTTPS
|
|
||||||
- `Referrer-Policy`: Control referrer information
|
|
||||||
- `Permissions-Policy`: Disable unnecessary browser features
|
|
||||||
|
|
||||||
### 5. **SSL/TLS Configuration**
|
|
||||||
- TLS 1.2 and 1.3 only
|
|
||||||
- Strong cipher suites
|
|
||||||
- OCSP stapling
|
|
||||||
- HSTS enabled
|
|
||||||
|
|
||||||
### 6. **PHP Security**
|
|
||||||
- `open_basedir` restriction
|
|
||||||
- Upload size limits
|
|
||||||
- Timeout limits
|
|
||||||
- Server tokens disabled
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
### Test Admin Password Protection
|
### Test Admin Authentication
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Should prompt for password
|
# Should return 401
|
||||||
curl -I https://posterg.erg.be/formulaire/
|
curl -I https://posterg.erg.be/admin/
|
||||||
|
|
||||||
# With credentials
|
# With credentials
|
||||||
curl -u admin:your_password https://posterg.erg.be/formulaire/
|
curl -u admin:password https://posterg.erg.be/admin/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Test Rate Limiting
|
### Test File Protection
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Make multiple rapid requests (should get 429 Too Many Requests after limit)
|
# Should return 403
|
||||||
for i in {1..50}; do curl -I https://posterg.erg.be/ 2>&1 | grep HTTP; done
|
curl -I https://posterg.erg.be/storage/test.db
|
||||||
```
|
curl -I https://posterg.erg.be/src/Database.php
|
||||||
|
|
||||||
### Test File Blocking
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Should return 403 Forbidden
|
|
||||||
curl -I https://posterg.erg.be/storage/posterg.db
|
|
||||||
curl -I https://posterg.erg.be/shared/Database.php
|
|
||||||
curl -I https://posterg.erg.be/README.md
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Test Security Headers
|
### Test Security Headers
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Check security headers
|
curl -I https://posterg.erg.be/ | grep -E "X-|Strict-Transport"
|
||||||
curl -I https://posterg.erg.be/ | grep -E "X-Frame|X-Content|Strict-Transport"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Monitoring and Logs
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Watch access logs
|
|
||||||
sudo tail -f /var/log/nginx/posterg_access.log
|
|
||||||
|
|
||||||
# Watch error logs
|
|
||||||
sudo tail -f /var/log/nginx/posterg_error.log
|
|
||||||
|
|
||||||
# Watch SSL access logs
|
|
||||||
sudo tail -f /var/log/nginx/posterg_ssl_access.log
|
|
||||||
|
|
||||||
# Check PHP-FPM logs
|
|
||||||
sudo tail -f /var/log/php8.2-fpm.log
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### "403 Forbidden" on admin panel
|
### 403 Forbidden on admin
|
||||||
- Check htpasswd file exists: `ls -l /etc/nginx/.htpasswd-posterg`
|
```bash
|
||||||
- Check file permissions: `sudo chmod 644 /etc/nginx/.htpasswd-posterg`
|
sudo ls -l /etc/nginx/.htpasswd-posterg
|
||||||
- Check credentials are correct
|
sudo chmod 644 /etc/nginx/.htpasswd-posterg
|
||||||
|
```
|
||||||
|
|
||||||
### "502 Bad Gateway"
|
### 502 Bad Gateway
|
||||||
- Check PHP-FPM is running: `sudo systemctl status php8.2-fpm`
|
```bash
|
||||||
- Check socket path in nginx config matches PHP-FPM config
|
sudo systemctl status php8.4-fpm
|
||||||
- Check PHP-FPM logs: `sudo tail /var/log/php8.2-fpm.log`
|
sudo systemctl restart php8.4-fpm
|
||||||
|
```
|
||||||
|
|
||||||
### "File not found" errors
|
### Configuration errors
|
||||||
- Check root path in nginx config
|
```bash
|
||||||
- Check file permissions
|
sudo nginx -t
|
||||||
- Check PHP-FPM open_basedir setting
|
```
|
||||||
|
|
||||||
### Rate limiting too strict
|
|
||||||
- Adjust `rate=` values in nginx config
|
|
||||||
- Adjust `burst=` values for each location
|
|
||||||
|
|
||||||
## Maintenance
|
## Maintenance
|
||||||
|
|
||||||
### Change Admin Password
|
### Change Admin Password
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Change password for existing user
|
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg admin
|
sudo htpasswd /etc/nginx/.htpasswd-posterg admin
|
||||||
|
|
||||||
# Remove a user
|
|
||||||
sudo htpasswd -D /etc/nginx/.htpasswd-posterg old_user
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Renew SSL Certificate
|
### Reload Configuration
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Manual renewal
|
sudo nginx -t && sudo systemctl reload nginx
|
||||||
sudo certbot renew
|
|
||||||
|
|
||||||
# Check expiry
|
|
||||||
sudo certbot certificates
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Update Configuration
|
## See Also
|
||||||
|
|
||||||
```bash
|
- **[docs/PRODUCTION_DEPLOYMENT.md](docs/PRODUCTION_DEPLOYMENT.md)** - Detailed deployment
|
||||||
# After modifying config file
|
- **[docs/QUICK_REFERENCE.md](docs/QUICK_REFERENCE.md)** - Command reference
|
||||||
sudo nginx -t
|
- **[docs/ADMIN_USERS.md](docs/ADMIN_USERS.md)** - User management
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
## Performance Tuning
|
|
||||||
|
|
||||||
### Enable Gzip Compression
|
|
||||||
|
|
||||||
Add to nginx config:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
gzip on;
|
|
||||||
gzip_vary on;
|
|
||||||
gzip_proxied any;
|
|
||||||
gzip_comp_level 6;
|
|
||||||
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
|
|
||||||
```
|
|
||||||
|
|
||||||
### Enable FastCGI Cache
|
|
||||||
|
|
||||||
For high-traffic sites, add FastCGI caching:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=POSTERG:100m inactive=60m;
|
|
||||||
fastcgi_cache_key "$scheme$request_method$host$request_uri";
|
|
||||||
```
|
|
||||||
|
|
||||||
## Security Checklist
|
|
||||||
|
|
||||||
- [ ] Admin password set and secured
|
|
||||||
- [ ] SSL/HTTPS enabled and working
|
|
||||||
- [ ] Database files not accessible via web
|
|
||||||
- [ ] Sensitive files (.md, .sql, .env) blocked
|
|
||||||
- [ ] Rate limiting configured
|
|
||||||
- [ ] Security headers enabled
|
|
||||||
- [ ] PHP open_basedir configured
|
|
||||||
- [ ] File permissions correct (644 for files, 755 for dirs)
|
|
||||||
- [ ] Logs monitored regularly
|
|
||||||
- [ ] Backups automated
|
|
||||||
|
|
||||||
## Additional Hardening (Optional)
|
|
||||||
|
|
||||||
### Install Fail2Ban
|
|
||||||
|
|
||||||
Protect against brute force attacks:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install fail2ban
|
|
||||||
|
|
||||||
# Create jail for nginx
|
|
||||||
sudo nano /etc/fail2ban/jail.local
|
|
||||||
```
|
|
||||||
|
|
||||||
Add:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[nginx-limit-req]
|
|
||||||
enabled = true
|
|
||||||
filter = nginx-limit-req
|
|
||||||
logpath = /var/log/nginx/posterg_error.log
|
|
||||||
maxretry = 5
|
|
||||||
bantime = 3600
|
|
||||||
```
|
|
||||||
|
|
||||||
### Enable UFW Firewall
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo ufw allow 22/tcp
|
|
||||||
sudo ufw allow 80/tcp
|
|
||||||
sudo ufw allow 443/tcp
|
|
||||||
sudo ufw enable
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database Encryption
|
|
||||||
|
|
||||||
Consider encrypting the SQLite database at rest using SQLCipher or dm-crypt/LUKS.
|
|
||||||
|
|||||||
@@ -1,352 +0,0 @@
|
|||||||
# Test Database Setup - Post-ERG
|
|
||||||
|
|
||||||
Complete guide for deploying and managing the test database on the production server.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 Quick Deploy
|
|
||||||
|
|
||||||
```bash
|
|
||||||
just test-deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
This automatically:
|
|
||||||
1. ✅ Creates `/var/www/html/storage/` directory
|
|
||||||
2. ✅ Uploads `test.db` to the server
|
|
||||||
3. ✅ Sets correct group ownership (`posterg`)
|
|
||||||
4. ✅ Sets correct permissions (775 for dir, 660 for file)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 Prerequisites (One-Time Setup)
|
|
||||||
|
|
||||||
### 1. Install PHP SQLite Extension
|
|
||||||
|
|
||||||
On the server:
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo bash /tmp/install-php-sqlite.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Or manually:
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install php8.4-sqlite3
|
|
||||||
sudo systemctl restart php8.4-fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Verify Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
php -m | grep sqlite3
|
|
||||||
# Should output: pdo_sqlite, sqlite3
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 How Database Selection Works
|
|
||||||
|
|
||||||
The system automatically detects which database to use:
|
|
||||||
|
|
||||||
1. **If `test.db` exists** → Uses test database
|
|
||||||
2. **Otherwise** → Uses production database (`posterg.db`)
|
|
||||||
|
|
||||||
This is configured in `shared/config.php`:
|
|
||||||
|
|
||||||
```php
|
|
||||||
function getDatabasePath() {
|
|
||||||
// If test.db exists, use it
|
|
||||||
if (file_exists(DB_TEST_PATH)) {
|
|
||||||
return DB_TEST_PATH;
|
|
||||||
}
|
|
||||||
// Otherwise use production database
|
|
||||||
return DB_PROD_PATH;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🧪 Complete Testing Workflow
|
|
||||||
|
|
||||||
### 1. Create Test Data Locally
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create empty test database from schema
|
|
||||||
just init-test-db
|
|
||||||
|
|
||||||
# Or create with sample fixtures
|
|
||||||
just create-fixtures
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Deploy Test Database
|
|
||||||
|
|
||||||
```bash
|
|
||||||
just test-deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Test the Site
|
|
||||||
|
|
||||||
Visit: https://posterg.erg.be/
|
|
||||||
|
|
||||||
The site now uses test data! 🎉
|
|
||||||
|
|
||||||
### 4. Check What Database is Being Used
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
php -r "require_once '/var/www/html/shared/Database.php'; echo 'Using: ' . Database::getInstance()->getDatabasePath() . PHP_EOL;"
|
|
||||||
```
|
|
||||||
|
|
||||||
Output will be:
|
|
||||||
- `/var/www/html/storage/test.db` (test mode)
|
|
||||||
- `/var/www/html/storage/posterg.db` (production mode)
|
|
||||||
|
|
||||||
### 5. Switch Back to Production
|
|
||||||
|
|
||||||
Simply remove the test database:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
rm /var/www/html/storage/test.db
|
|
||||||
```
|
|
||||||
|
|
||||||
The site automatically switches to production database.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔒 Permissions Explained
|
|
||||||
|
|
||||||
### Directory Permissions
|
|
||||||
|
|
||||||
```
|
|
||||||
drwxrwxr-x theophile posterg /var/www/html/storage/
|
|
||||||
```
|
|
||||||
|
|
||||||
- **775**: Owner and group can read/write/execute, others can read/execute
|
|
||||||
- **Group: posterg**: `www-data` is member of this group
|
|
||||||
- **Writable by group**: SQLite needs to create journal/temp files
|
|
||||||
|
|
||||||
### File Permissions
|
|
||||||
|
|
||||||
```
|
|
||||||
-rw-rw---- theophile posterg test.db
|
|
||||||
```
|
|
||||||
|
|
||||||
- **660**: Owner and group can read/write, others have no access
|
|
||||||
- **Group: posterg**: `www-data` can read/write the database
|
|
||||||
- **No public access**: Security - only PHP-FPM can access
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🐛 Troubleshooting
|
|
||||||
|
|
||||||
### Site Shows Empty Page or Error
|
|
||||||
|
|
||||||
**Check error logs:**
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
tail -f /var/log/nginx/posterg_error.log
|
|
||||||
```
|
|
||||||
|
|
||||||
### "could not find driver"
|
|
||||||
|
|
||||||
**SQLite extension not installed:**
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sudo apt install php8.4-sqlite3
|
|
||||||
sudo systemctl restart php8.4-fpm
|
|
||||||
```
|
|
||||||
|
|
||||||
### "unable to open database file"
|
|
||||||
|
|
||||||
**Wrong permissions:**
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
# Fix group ownership
|
|
||||||
chgrp posterg /var/www/html/database /var/www/html/storage/test.db
|
|
||||||
|
|
||||||
# Fix permissions
|
|
||||||
chmod 775 /var/www/html/database
|
|
||||||
chmod 660 /var/www/html/storage/test.db
|
|
||||||
```
|
|
||||||
|
|
||||||
### "SQLSTATE[HY000]: General error: 8 attempt to write a readonly database"
|
|
||||||
|
|
||||||
**Directory not writable:**
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
chmod 775 /var/www/html/database
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database Doesn't Update
|
|
||||||
|
|
||||||
**Clear SQLite cache:**
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
rm -f /var/www/html/storage/test.db-journal
|
|
||||||
rm -f /var/www/html/storage/test.db-shm
|
|
||||||
rm -f /var/www/html/storage/test.db-wal
|
|
||||||
```
|
|
||||||
|
|
||||||
Then redeploy:
|
|
||||||
```bash
|
|
||||||
just test-deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Check Database Stats
|
|
||||||
|
|
||||||
### On Server
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
cd /var/www/html
|
|
||||||
|
|
||||||
# Count theses
|
|
||||||
php -r "require_once 'shared/Database.php'; echo 'Theses: ' . Database::getInstance()->countPublishedTheses() . PHP_EOL;"
|
|
||||||
|
|
||||||
# Check database file
|
|
||||||
ls -lh database/test.db
|
|
||||||
```
|
|
||||||
|
|
||||||
### From Local Machine
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Show stats from local test database
|
|
||||||
sqlite3 database/test.db "SELECT COUNT(*) FROM theses;"
|
|
||||||
sqlite3 database/test.db "SELECT COUNT(*) FROM theses WHERE is_published = 1;"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 Update Test Data
|
|
||||||
|
|
||||||
### Update Locally and Redeploy
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Make changes to local test database
|
|
||||||
sqlite3 database/test.db
|
|
||||||
# ... make changes ...
|
|
||||||
|
|
||||||
# Deploy updated database
|
|
||||||
just test-deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
### Update Directly on Server
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
sqlite3 /var/www/html/storage/test.db
|
|
||||||
# ... make changes ...
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ Important Notes
|
|
||||||
|
|
||||||
### Production Safety
|
|
||||||
|
|
||||||
The `just deploy` command **excludes all `.db` files** by default:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Safe - deploys code only
|
|
||||||
just deploy
|
|
||||||
just deploy-public
|
|
||||||
just deploy-admin
|
|
||||||
|
|
||||||
# Safe - deploys schema/docs only
|
|
||||||
just deploy-database
|
|
||||||
|
|
||||||
# Requires explicit command - deploys test.db
|
|
||||||
just test-deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
This prevents accidentally overwriting production data!
|
|
||||||
|
|
||||||
### Never Commit test.db to Git
|
|
||||||
|
|
||||||
The `.gitignore` already excludes it:
|
|
||||||
|
|
||||||
```
|
|
||||||
*.db
|
|
||||||
*.db-journal
|
|
||||||
```
|
|
||||||
|
|
||||||
### Backup Production Database
|
|
||||||
|
|
||||||
Before deploying test database, backup production if needed:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ssh posterg
|
|
||||||
cp /var/www/html/storage/posterg.db /var/www/html/storage/posterg.db.backup.$(date +%Y%m%d)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎓 Database File Locations
|
|
||||||
|
|
||||||
### Local (Development)
|
|
||||||
|
|
||||||
```
|
|
||||||
/home/theophile/dev/posterg-website/
|
|
||||||
└── database/
|
|
||||||
├── schema.sql # Database schema
|
|
||||||
├── test.db # Test database (gitignored)
|
|
||||||
└── fixtures/ # Test data generators
|
|
||||||
```
|
|
||||||
|
|
||||||
### Server (Production)
|
|
||||||
|
|
||||||
```
|
|
||||||
/var/www/html/
|
|
||||||
└── database/
|
|
||||||
├── posterg.db # Production database
|
|
||||||
└── test.db # Test database (if deployed)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 Related Commands
|
|
||||||
|
|
||||||
| Command | Description |
|
|
||||||
|---------|-------------|
|
|
||||||
| `just init-test-db` | Create empty test database |
|
|
||||||
| `just create-fixtures` | Create test database with sample data |
|
|
||||||
| `just test-deploy` | Deploy test database to server |
|
|
||||||
| `just stats-public` | Show local database statistics |
|
|
||||||
| `just query-db` | Open SQLite prompt for local test.db |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ Deployment Checklist
|
|
||||||
|
|
||||||
After running `just test-deploy`, verify:
|
|
||||||
|
|
||||||
- [ ] Database file exists: `ssh posterg "ls -la /var/www/html/storage/test.db"`
|
|
||||||
- [ ] Correct permissions: `-rw-rw---- theophile posterg`
|
|
||||||
- [ ] Directory writable: `drwxrwxr-x theophile posterg`
|
|
||||||
- [ ] Site loads: Visit https://posterg.erg.be/
|
|
||||||
- [ ] No errors in logs: `ssh posterg "tail /var/log/nginx/posterg_error.log"`
|
|
||||||
- [ ] Database accessible: Test with admin panel
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 Success!
|
|
||||||
|
|
||||||
When working correctly:
|
|
||||||
|
|
||||||
- ✅ Main page shows test data
|
|
||||||
- ✅ Search works with test data
|
|
||||||
- ✅ Admin panel loads form
|
|
||||||
- ✅ No database errors in logs
|
|
||||||
- ✅ Can create/edit/delete test entries
|
|
||||||
|
|
||||||
To switch back to production, just:
|
|
||||||
```bash
|
|
||||||
ssh posterg "rm /var/www/html/storage/test.db"
|
|
||||||
```
|
|
||||||
|
|
||||||
Site automatically uses `posterg.db` again! 🚀
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Deploy production nginx configuration for Post-ERG (NEW STRUCTURE)
|
|
||||||
# This script applies the nginx config for /var/www/posterg/public/ structure
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🚀 Post-ERG Production Deployment (NEW STRUCTURE)"
|
|
||||||
echo "=================================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Colors
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
# Check if running as root
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
|
||||||
echo -e "${RED}Error: This script must be run as root (use sudo)${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "📋 Step 1: Fixing file permissions..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
# Change ownership to www-data:posterg
|
|
||||||
chown -R www-data:posterg /var/www/posterg/
|
|
||||||
echo "✓ Changed ownership to www-data:posterg"
|
|
||||||
|
|
||||||
# Set directory permissions (755)
|
|
||||||
find /var/www/posterg -type d -exec chmod 755 {} \;
|
|
||||||
echo "✓ Set directory permissions to 755"
|
|
||||||
|
|
||||||
# Set file permissions (644)
|
|
||||||
find /var/www/posterg -type f -exec chmod 644 {} \;
|
|
||||||
echo "✓ Set file permissions to 644"
|
|
||||||
|
|
||||||
# Make storage directory writable by group
|
|
||||||
if [ -d "/var/www/posterg/storage" ]; then
|
|
||||||
chmod 775 /var/www/posterg/storage
|
|
||||||
echo "✓ Made storage directory group-writable (775)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Fix database file permissions
|
|
||||||
if [ -f "/var/www/posterg/storage/test.db" ]; then
|
|
||||||
chmod 660 /var/www/posterg/storage/test.db
|
|
||||||
chown www-data:posterg /var/www/posterg/storage/test.db
|
|
||||||
echo "✓ Fixed database file permissions (660)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make admin upload directories writable by group
|
|
||||||
if [ -d "/var/www/posterg/public/admin/data" ]; then
|
|
||||||
find /var/www/posterg/public/admin/data -type d -exec chmod 775 {} \;
|
|
||||||
echo "✓ Made admin upload directories group-writable"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Step 2: Deploying nginx configuration..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
# Backup existing config
|
|
||||||
if [ -f "/etc/nginx/sites-available/posterg" ]; then
|
|
||||||
cp /etc/nginx/sites-available/posterg /etc/nginx/sites-available/posterg.backup.$(date +%Y%m%d_%H%M%S)
|
|
||||||
echo "✓ Backed up existing config"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy new config
|
|
||||||
if [ -f "/tmp/posterg.conf" ]; then
|
|
||||||
cp /tmp/posterg.conf /etc/nginx/sites-available/posterg
|
|
||||||
echo "✓ Installed new nginx config"
|
|
||||||
else
|
|
||||||
echo -e "${RED}Error: /tmp/posterg.conf not found${NC}"
|
|
||||||
echo "Run 'just deploy-nginx' first"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test nginx configuration
|
|
||||||
echo ""
|
|
||||||
echo "📋 Step 3: Testing nginx configuration..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
if nginx -t; then
|
|
||||||
echo -e "${GREEN}✓ Nginx configuration is valid${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗ Nginx configuration has errors!${NC}"
|
|
||||||
echo "Restoring backup..."
|
|
||||||
cp /etc/nginx/sites-available/posterg.backup.$(date +%Y%m%d_%H%M%S | tail -1) /etc/nginx/sites-available/posterg
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Step 4: Summary..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
echo -e "${GREEN}✓ Permissions fixed${NC}"
|
|
||||||
echo -e "${GREEN}✓ Nginx config installed${NC}"
|
|
||||||
echo -e "${GREEN}✓ Configuration validated${NC}"
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}Ready to reload nginx!${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "Run: ${GREEN}sudo systemctl reload nginx${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "After reload, verify:"
|
|
||||||
echo " • https://posterg.erg.be/"
|
|
||||||
echo " • https://posterg.erg.be/admin/"
|
|
||||||
echo " • https://posterg.erg.be/storage/test.db (should 404)"
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Deploy production nginx configuration and fix permissions for Post-ERG
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🚀 Post-ERG Production Deployment"
|
|
||||||
echo "=================================="
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Colors
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
# Check if running as root
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
|
||||||
echo -e "${RED}Error: This script must be run as root (use sudo)${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "📋 Step 1: Fixing file permissions..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
# Change group to posterg (www-data is member of this group)
|
|
||||||
chown -R theophile:posterg /var/www/html/
|
|
||||||
echo "✓ Changed group to posterg"
|
|
||||||
|
|
||||||
# Set directory permissions (755 - readable/executable by everyone)
|
|
||||||
find /var/www/html -type d -exec chmod 755 {} \;
|
|
||||||
echo "✓ Set directory permissions to 755"
|
|
||||||
|
|
||||||
# Set file permissions (640 - owner read/write, group read)
|
|
||||||
find /var/www/html -type f -exec chmod 640 {} \;
|
|
||||||
echo "✓ Set file permissions to 640"
|
|
||||||
|
|
||||||
# Make upload directories writable by group (for www-data to write)
|
|
||||||
if [ -d "/var/www/html/formulaire/data/theses" ]; then
|
|
||||||
chmod 775 /var/www/html/formulaire/data/theses
|
|
||||||
chmod 775 /var/www/html/formulaire/data/covers
|
|
||||||
echo "✓ Set upload directories to 775"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Protect database if it exists
|
|
||||||
if [ -f "/var/www/html/storage/posterg.db" ]; then
|
|
||||||
chmod 660 /var/www/html/storage/posterg.db
|
|
||||||
chown www-data:posterg /var/www/html/storage/posterg.db
|
|
||||||
echo "✓ Protected database file"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Step 2: Checking prerequisites..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
# Check if htpasswd is available
|
|
||||||
if ! command -v htpasswd &> /dev/null; then
|
|
||||||
echo -e "${YELLOW}⚠️ htpasswd not found, installing apache2-utils...${NC}"
|
|
||||||
apt-get update -qq
|
|
||||||
apt-get install -y apache2-utils
|
|
||||||
echo -e "${GREEN}✓ apache2-utils installed${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if htpasswd file exists
|
|
||||||
if [ ! -f "/etc/nginx/.htpasswd-posterg" ]; then
|
|
||||||
echo -e "${YELLOW}⚠️ Warning: /etc/nginx/.htpasswd-posterg not found${NC}"
|
|
||||||
echo " Creating it now..."
|
|
||||||
echo ""
|
|
||||||
echo "Please enter admin username:"
|
|
||||||
read -r ADMIN_USER
|
|
||||||
htpasswd -c /etc/nginx/.htpasswd-posterg "$ADMIN_USER"
|
|
||||||
echo -e "${GREEN}✓ Password file created${NC}"
|
|
||||||
echo ""
|
|
||||||
else
|
|
||||||
echo "✓ Password file exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if config file was uploaded
|
|
||||||
if [ ! -f "/tmp/posterg.conf" ]; then
|
|
||||||
echo -e "${RED}✗ Error: /tmp/posterg.conf not found${NC}"
|
|
||||||
echo "Please upload it first: rsync -vur ./nginx/posterg-production.conf posterg:/tmp/posterg.conf"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Step 3: Installing nginx configuration..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
# Backup existing config if it exists
|
|
||||||
if [ -f "/etc/nginx/sites-available/posterg" ]; then
|
|
||||||
cp /etc/nginx/sites-available/posterg /etc/nginx/sites-available/posterg.backup.$(date +%Y%m%d_%H%M%S)
|
|
||||||
echo "✓ Backed up existing config"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy new configuration
|
|
||||||
cp /tmp/posterg.conf /etc/nginx/sites-available/posterg
|
|
||||||
echo "✓ Installed configuration to /etc/nginx/sites-available/posterg"
|
|
||||||
|
|
||||||
# Create symlink
|
|
||||||
if [ ! -L "/etc/nginx/sites-enabled/posterg" ]; then
|
|
||||||
ln -s /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/posterg
|
|
||||||
echo "✓ Created symlink in sites-enabled"
|
|
||||||
else
|
|
||||||
echo "✓ Symlink already exists"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Remove default site
|
|
||||||
if [ -L "/etc/nginx/sites-enabled/default" ]; then
|
|
||||||
rm /etc/nginx/sites-enabled/default
|
|
||||||
echo "✓ Disabled default site"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Step 4: Testing nginx configuration..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
if nginx -t; then
|
|
||||||
echo -e "${GREEN}✓ Nginx configuration is valid${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗ Nginx configuration has errors!${NC}"
|
|
||||||
echo "Restoring backup..."
|
|
||||||
if ls /etc/nginx/sites-available/posterg.backup* 1> /dev/null 2>&1; then
|
|
||||||
BACKUP=$(ls -t /etc/nginx/sites-available/posterg.backup* | head -1)
|
|
||||||
cp "$BACKUP" /etc/nginx/sites-available/posterg
|
|
||||||
echo "Configuration restored from backup"
|
|
||||||
fi
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Step 5: Reloading nginx..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
if systemctl reload nginx; then
|
|
||||||
echo -e "${GREEN}✓ Nginx reloaded successfully${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗ Failed to reload nginx${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "📋 Step 6: Verifying services..."
|
|
||||||
echo "--------------------------------------"
|
|
||||||
|
|
||||||
# Check PHP-FPM
|
|
||||||
if systemctl is-active --quiet php8.4-fpm; then
|
|
||||||
echo -e "${GREEN}✓ PHP 8.4-FPM is running${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}⚠️ PHP-FPM is not running, starting it...${NC}"
|
|
||||||
systemctl start php8.4-fpm
|
|
||||||
systemctl enable php8.4-fpm
|
|
||||||
echo -e "${GREEN}✓ PHP-FPM started${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check nginx
|
|
||||||
if systemctl is-active --quiet nginx; then
|
|
||||||
echo -e "${GREEN}✓ Nginx is running${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗ Nginx is not running!${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "═══════════════════════════════════════"
|
|
||||||
echo -e "${GREEN}✅ Deployment Complete!${NC}"
|
|
||||||
echo "═══════════════════════════════════════"
|
|
||||||
echo ""
|
|
||||||
echo "🧪 Quick Tests:"
|
|
||||||
echo " • Test public site: curl -I http://localhost/"
|
|
||||||
echo " • Test admin panel: curl -I http://localhost/formulaire/"
|
|
||||||
echo " • Test PHP: curl http://localhost/index.php"
|
|
||||||
echo ""
|
|
||||||
echo "📊 View logs:"
|
|
||||||
echo " • Access log: tail -f /var/log/nginx/posterg_access.log"
|
|
||||||
echo " • Error log: tail -f /var/log/nginx/posterg_error.log"
|
|
||||||
echo ""
|
|
||||||
echo "🔒 Security Checks:"
|
|
||||||
echo " • Database blocked: curl -I http://localhost/storage/posterg.db"
|
|
||||||
echo " • MD files blocked: curl -I http://localhost/README.md"
|
|
||||||
echo " • Source blocked: curl -I http://localhost/src/Database.php"
|
|
||||||
echo " • Templates blocked: curl -I http://localhost/templates/header.php"
|
|
||||||
echo " • Config blocked: curl -I http://localhost/config/bootstrap.php"
|
|
||||||
echo ""
|
|
||||||
@@ -9,6 +9,10 @@ Quick guide to manage admin users for the Post-ERG admin panel.
|
|||||||
### Interactive Menu (Recommended)
|
### Interactive Menu (Recommended)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# From your local machine
|
||||||
|
just manage-admin-users
|
||||||
|
|
||||||
|
# Then on the server
|
||||||
ssh posterg
|
ssh posterg
|
||||||
sudo bash /tmp/manage-admin-users.sh
|
sudo bash /tmp/manage-admin-users.sh
|
||||||
```
|
```
|
||||||
@@ -71,10 +75,10 @@ To upload the interactive management script to the server:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# From your local machine
|
# From your local machine
|
||||||
just deploy-admin-tools
|
just manage-admin-users
|
||||||
|
|
||||||
# Or manually:
|
# Or manually:
|
||||||
rsync -vur ./nginx/manage-admin-users.sh posterg:/tmp/manage-admin-users.sh
|
rsync -v scripts/manage-admin-users.sh posterg:/tmp/manage-admin-users.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -82,7 +86,7 @@ rsync -vur ./nginx/manage-admin-users.sh posterg:/tmp/manage-admin-users.sh
|
|||||||
## 🔑 Current Setup
|
## 🔑 Current Setup
|
||||||
|
|
||||||
After deployment, your admin panel has:
|
After deployment, your admin panel has:
|
||||||
- **URL:** https://posterg.erg.be/formulaire/
|
- **URL:** https://posterg.erg.be/admin/
|
||||||
- **Current user:** `test_posterg_22@`
|
- **Current user:** `test_posterg_22@`
|
||||||
- **Password:** Set during initial deployment
|
- **Password:** Set during initial deployment
|
||||||
|
|
||||||
@@ -127,7 +131,7 @@ sudo htpasswd /etc/nginx/.htpasswd-posterg admin2
|
|||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg admin3
|
sudo htpasswd /etc/nginx/.htpasswd-posterg admin3
|
||||||
```
|
```
|
||||||
|
|
||||||
All users can log into `/formulaire/` with their own credentials.
|
All users can log into `/admin/` with their own credentials.
|
||||||
|
|
||||||
### Scenario 5: Start Over with New Username
|
### Scenario 5: Start Over with New Username
|
||||||
|
|
||||||
@@ -145,11 +149,11 @@ After changing users/passwords:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Test that password is required
|
# Test that password is required
|
||||||
curl -I https://posterg.erg.be/formulaire/
|
curl -I https://posterg.erg.be/admin/
|
||||||
# Should return: 401 Unauthorized
|
# Should return: 401 Unauthorized
|
||||||
|
|
||||||
# Test with credentials
|
# Test with credentials
|
||||||
curl -u username:password https://posterg.erg.be/formulaire/
|
curl -u username:password https://posterg.erg.be/admin/
|
||||||
# Should return: 200 OK
|
# Should return: 200 OK
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -193,7 +197,7 @@ username:$apr1$encrypted_password_hash
|
|||||||
```bash
|
```bash
|
||||||
# Check who's accessing the admin panel
|
# Check who's accessing the admin panel
|
||||||
ssh posterg
|
ssh posterg
|
||||||
sudo grep "formulaire" /var/log/nginx/posterg_access.log
|
sudo grep "admin" /var/log/nginx/posterg_access.log
|
||||||
```
|
```
|
||||||
|
|
||||||
5. **Backup Password File**
|
5. **Backup Password File**
|
||||||
@@ -263,7 +267,7 @@ No action needed! Changes to the password file take effect immediately.
|
|||||||
|
|
||||||
You can verify with:
|
You can verify with:
|
||||||
```bash
|
```bash
|
||||||
curl -u username:password https://posterg.erg.be/formulaire/
|
curl -u username:password https://posterg.erg.be/admin/
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
# `.htaccess` → nginx migration (item #6)
|
# `.htaccess` → nginx migration
|
||||||
|
|
||||||
> **Problem:** `public/admin/.htaccess` contained Apache-specific security
|
> **Problem:** `public/admin/.htaccess` contained Apache-specific security
|
||||||
> directives that nginx **silently ignores**. None of the rules were active
|
> directives that nginx **silently ignores**. None of the rules were active
|
||||||
> in production.
|
> in production.
|
||||||
|
|
||||||
|
> **Status:** Migrated into `nginx/posterg.conf`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Rules migrated into `nginx/posterg.conf`
|
## Rules migrated into `nginx/posterg.conf`
|
||||||
@@ -11,7 +11,7 @@ The admin panel uses **two independent authentication layers** with a single UX
|
|||||||
| Layer | Mechanism | Configured by |
|
| Layer | Mechanism | Configured by |
|
||||||
|-------|-----------|---------------|
|
|-------|-----------|---------------|
|
||||||
| **1st** | nginx HTTP Basic Auth | `/etc/nginx/.htpasswd-posterg` (see `ADMIN_USERS.md`) |
|
| **1st** | nginx HTTP Basic Auth | `/etc/nginx/.htpasswd-posterg` (see `ADMIN_USERS.md`) |
|
||||||
| **2nd** | PHP session guard (`lib/AdminAuth.php`) | `config/admin_credentials.php` |
|
| **2nd** | PHP session guard (`src/AdminAuth.php`) | `config/admin_credentials.php` |
|
||||||
|
|
||||||
The user only sees **one prompt** (the browser Basic Auth dialog). PHP reads the
|
The user only sees **one prompt** (the browser Basic Auth dialog). PHP reads the
|
||||||
same password from `$_SERVER['PHP_AUTH_PW']` and validates it independently with
|
same password from `$_SERVER['PHP_AUTH_PW']` and validates it independently with
|
||||||
@@ -103,7 +103,7 @@ nginx Basic Auth invalidation requires closing the browser tab / window.
|
|||||||
|
|
||||||
| File | Change |
|
| File | Change |
|
||||||
|------|--------|
|
|------|--------|
|
||||||
| `lib/AdminAuth.php` | New — auth guard class |
|
| `src/AdminAuth.php` | New — auth guard class |
|
||||||
| `config/admin_credentials.php` | New — credential store (gitignored) |
|
| `config/admin_credentials.php` | New — credential store (gitignored) |
|
||||||
| `config/admin_credentials.example.php` | New — example / template |
|
| `config/admin_credentials.example.php` | New — example / template |
|
||||||
| `config/bootstrap.php` | Load credentials on startup |
|
| `config/bootstrap.php` | Load credentials on startup |
|
||||||
210
nginx/docs/PRODUCTION_DEPLOYMENT.md
Normal file
210
nginx/docs/PRODUCTION_DEPLOYMENT.md
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
# Production Deployment Guide - Post-ERG
|
||||||
|
|
||||||
|
This guide covers deploying the production nginx configuration with proper security and permissions.
|
||||||
|
|
||||||
|
## 🎯 Overview
|
||||||
|
|
||||||
|
- **Server**: posterg.erg.be (internal IP: 192.168.6.125)
|
||||||
|
- **PHP Version**: 8.4
|
||||||
|
- **SSL/TLS**: Handled by upstream reverse proxy
|
||||||
|
- **Document Root**: `/var/www/posterg/public/`
|
||||||
|
|
||||||
|
## 🚀 Quick Deployment
|
||||||
|
|
||||||
|
From your local machine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy nginx config and upload deployment script
|
||||||
|
just deploy-nginx
|
||||||
|
|
||||||
|
# Then on the server:
|
||||||
|
ssh posterg
|
||||||
|
sudo bash /tmp/deploy-server.sh
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
This uploads:
|
||||||
|
- `nginx/posterg.conf` → `/tmp/posterg.conf`
|
||||||
|
- `scripts/deploy-server.sh` → `/tmp/deploy-server.sh`
|
||||||
|
|
||||||
|
## 📋 Step-by-Step Deployment
|
||||||
|
|
||||||
|
### 1. Set Up Admin Password (First Time Only)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
sudo htpasswd -c /etc/nginx/.htpasswd-posterg admin
|
||||||
|
# Enter a strong password when prompted
|
||||||
|
```
|
||||||
|
|
||||||
|
**💡 Tip**: Generate a strong password:
|
||||||
|
```bash
|
||||||
|
openssl rand -base64 32
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Deploy Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your local machine
|
||||||
|
just deploy-nginx
|
||||||
|
|
||||||
|
# On the server
|
||||||
|
sudo bash /tmp/deploy-server.sh
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
The script will:
|
||||||
|
- ✅ Fix file permissions (set to www-data:posterg)
|
||||||
|
- ✅ Install nginx configuration
|
||||||
|
- ✅ Test nginx configuration
|
||||||
|
- ✅ Check PHP-FPM status
|
||||||
|
|
||||||
|
## 🔧 Manual Deployment (Alternative)
|
||||||
|
|
||||||
|
### Step 1: Fix Permissions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
|
||||||
|
# Set correct ownership
|
||||||
|
sudo chown -R www-data:posterg /var/www/posterg/
|
||||||
|
|
||||||
|
# Set directory permissions
|
||||||
|
sudo find /var/www/posterg -type d -exec chmod 755 {} \;
|
||||||
|
|
||||||
|
# Set file permissions
|
||||||
|
sudo find /var/www/posterg -type f -exec chmod 644 {} \;
|
||||||
|
|
||||||
|
# Make storage writable
|
||||||
|
sudo chmod 775 /var/www/posterg/storage
|
||||||
|
|
||||||
|
# Protect database
|
||||||
|
sudo chmod 660 /var/www/posterg/storage/test.db
|
||||||
|
sudo chown www-data:posterg /var/www/posterg/storage/test.db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Deploy Nginx Config
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy config
|
||||||
|
sudo cp /tmp/posterg.conf /etc/nginx/sites-available/posterg
|
||||||
|
|
||||||
|
# Enable site and disable default
|
||||||
|
sudo ln -sf /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/posterg
|
||||||
|
sudo rm -f /etc/nginx/sites-enabled/default
|
||||||
|
|
||||||
|
# Test and reload
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 Testing
|
||||||
|
|
||||||
|
### Test Public Site
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Should return 200 OK
|
||||||
|
curl -I https://posterg.erg.be/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Admin Protection
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Should return 401 Unauthorized
|
||||||
|
curl -I https://posterg.erg.be/admin/
|
||||||
|
|
||||||
|
# With credentials
|
||||||
|
curl -u admin:your_password https://posterg.erg.be/admin/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test File Protection
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Should return 403 Forbidden
|
||||||
|
curl -I https://posterg.erg.be/storage/test.db
|
||||||
|
curl -I https://posterg.erg.be/src/Database.php
|
||||||
|
curl -I https://posterg.erg.be/config/bootstrap.php
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Security Headers
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -I https://posterg.erg.be/ | grep -E "X-Frame|X-Content|Strict-Transport"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Troubleshooting
|
||||||
|
|
||||||
|
### Still Getting 403 Forbidden
|
||||||
|
|
||||||
|
**Check file permissions:**
|
||||||
|
```bash
|
||||||
|
ls -la /var/www/posterg/public/index.php
|
||||||
|
groups www-data # Should include posterg
|
||||||
|
```
|
||||||
|
|
||||||
|
### 502 Bad Gateway
|
||||||
|
|
||||||
|
**Check PHP-FPM:**
|
||||||
|
```bash
|
||||||
|
sudo systemctl status php8.4-fpm
|
||||||
|
sudo systemctl restart php8.4-fpm
|
||||||
|
```
|
||||||
|
|
||||||
|
### Admin Password Not Working
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo htpasswd /etc/nginx/.htpasswd-posterg admin
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Monitoring
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Watch logs
|
||||||
|
sudo tail -f /var/log/nginx/posterg_access.log
|
||||||
|
sudo tail -f /var/log/nginx/posterg_error.log
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
sudo systemctl status nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 Security Checklist
|
||||||
|
|
||||||
|
After deployment, verify:
|
||||||
|
|
||||||
|
- [ ] Public site accessible at https://posterg.erg.be/
|
||||||
|
- [ ] Admin panel requires password
|
||||||
|
- [ ] Database files return 403 Forbidden
|
||||||
|
- [ ] Source files return 403 Forbidden
|
||||||
|
- [ ] Security headers present
|
||||||
|
- [ ] PHP-FPM running
|
||||||
|
|
||||||
|
## 🔄 Updating the Site
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy code changes
|
||||||
|
just deploy
|
||||||
|
|
||||||
|
# Reload nginx if config changed
|
||||||
|
ssh posterg "sudo systemctl reload nginx"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🆘 Emergency Recovery
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Restore default nginx config
|
||||||
|
ssh posterg
|
||||||
|
sudo rm /etc/nginx/sites-enabled/posterg
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
|
||||||
|
# Reset permissions
|
||||||
|
sudo chown -R www-data:posterg /var/www/posterg/
|
||||||
|
sudo find /var/www/posterg -type d -exec chmod 755 {} \;
|
||||||
|
sudo find /var/www/posterg -type f -exec chmod 644 {} \;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**See also:**
|
||||||
|
- [QUICK_REFERENCE.md](QUICK_REFERENCE.md) - Command reference
|
||||||
|
- [ADMIN_USERS.md](ADMIN_USERS.md) - User management
|
||||||
|
- [SECURITY_HEADERS.md](SECURITY_HEADERS.md) - Security headers
|
||||||
@@ -3,22 +3,13 @@
|
|||||||
## Setup Commands
|
## Setup Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Make setup script executable
|
|
||||||
chmod +x nginx/setup-password.sh
|
|
||||||
|
|
||||||
# Run password setup (as root)
|
|
||||||
sudo ./nginx/setup-password.sh
|
|
||||||
|
|
||||||
# Copy nginx config
|
# Copy nginx config
|
||||||
sudo cp nginx/posterg.conf /etc/nginx/sites-available/posterg
|
sudo cp nginx/posterg.conf /etc/nginx/sites-available/posterg
|
||||||
|
|
||||||
# Enable site
|
|
||||||
sudo ln -s /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/
|
sudo ln -s /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/
|
||||||
|
sudo rm -f /etc/nginx/sites-enabled/default
|
||||||
|
|
||||||
# Test configuration
|
# Test and reload
|
||||||
sudo nginx -t
|
sudo nginx -t
|
||||||
|
|
||||||
# Reload nginx
|
|
||||||
sudo systemctl reload nginx
|
sudo systemctl reload nginx
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -27,6 +18,10 @@ sudo systemctl reload nginx
|
|||||||
### Password Management
|
### Password Management
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Interactive menu (recommended)
|
||||||
|
sudo bash /tmp/manage-admin-users.sh
|
||||||
|
|
||||||
|
# Or manual commands:
|
||||||
# Add new user
|
# Add new user
|
||||||
sudo htpasswd /etc/nginx/.htpasswd-posterg username
|
sudo htpasswd /etc/nginx/.htpasswd-posterg username
|
||||||
|
|
||||||
@@ -103,10 +98,10 @@ sudo certbot renew --dry-run
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Should require password (returns 401)
|
# Should require password (returns 401)
|
||||||
curl -I https://posterg.erg.be/formulaire/
|
curl -I https://posterg.erg.be/admin/
|
||||||
|
|
||||||
# With authentication
|
# With authentication
|
||||||
curl -u admin:password https://posterg.erg.be/formulaire/
|
curl -u admin:password https://posterg.erg.be/admin/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Test Rate Limiting
|
### Test Rate Limiting
|
||||||
@@ -173,7 +168,7 @@ sudo tail -50 /var/log/nginx/error.log
|
|||||||
```bash
|
```bash
|
||||||
# Disable password protection temporarily
|
# Disable password protection temporarily
|
||||||
sudo nano /etc/nginx/sites-available/posterg
|
sudo nano /etc/nginx/sites-available/posterg
|
||||||
# Comment out these lines in /formulaire/ location:
|
# Comment out these lines in /admin/ location:
|
||||||
# auth_basic "Admin Access - Post-ERG";
|
# auth_basic "Admin Access - Post-ERG";
|
||||||
# auth_basic_user_file /etc/nginx/.htpasswd-posterg;
|
# auth_basic_user_file /etc/nginx/.htpasswd-posterg;
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
These were previously declared in `public/admin/.htaccess` as Apache
|
These were previously declared in `public/admin/.htaccess` as Apache
|
||||||
`mod_headers` directives, which nginx silently ignores. They are now
|
`mod_headers` directives, which nginx silently ignores. They are now
|
||||||
|
properly configured in `nginx/posterg.conf`.
|
||||||
enforced directly; see `HTACCESS_TO_NGINX.md` for the full migration log.
|
enforced directly; see `HTACCESS_TO_NGINX.md` for the full migration log.
|
||||||
|
|
||||||
## Intentionally omitted headers
|
## Intentionally omitted headers
|
||||||
152
nginx/docs/TEST_DATABASE_SETUP.md
Normal file
152
nginx/docs/TEST_DATABASE_SETUP.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# Test Database Setup - Post-ERG
|
||||||
|
|
||||||
|
Guide for deploying the test database to production server.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Quick Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just deploy-db
|
||||||
|
```
|
||||||
|
|
||||||
|
This automatically:
|
||||||
|
1. ✅ Checks remote DB doesn't exist (safety check)
|
||||||
|
2. ✅ Uploads `storage/test.db` to the server
|
||||||
|
3. ✅ Sets correct permissions (660, www-data:posterg)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Prerequisites (One-Time Setup)
|
||||||
|
|
||||||
|
### 1. Install PHP SQLite Extension
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install php8.4-sqlite3
|
||||||
|
sudo systemctl restart php8.4-fpm
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Verify Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
php -m | grep sqlite3
|
||||||
|
# Should output: pdo_sqlite, sqlite3
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Complete Testing Workflow
|
||||||
|
|
||||||
|
### 1. Create Test Data Locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create empty test database from schema
|
||||||
|
just init-db
|
||||||
|
|
||||||
|
# Or create with sample fixtures
|
||||||
|
just fixtures
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Deploy Test Database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
just deploy-db
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Test the Site
|
||||||
|
|
||||||
|
Visit: https://posterg.erg.be/
|
||||||
|
|
||||||
|
### 4. Check What Database is Being Used
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
php -r "require_once '/var/www/posterg/src/Database.php'; echo 'Using: ' . Database::getInstance()->getDatabasePath() . PHP_EOL;"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Switch Back to Production
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
rm /var/www/posterg/storage/test.db
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 Permissions Explained
|
||||||
|
|
||||||
|
```
|
||||||
|
/var/www/posterg/storage/
|
||||||
|
drwxrwxr-x www-data posterg # 775 - group writable
|
||||||
|
|
||||||
|
/var/www/posterg/storage/test.db
|
||||||
|
-rw-rw---- www-data posterg # 660 - owner/group read/write
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Troubleshooting
|
||||||
|
|
||||||
|
### "could not find driver"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
sudo apt install php8.4-sqlite3
|
||||||
|
sudo systemctl restart php8.4-fpm
|
||||||
|
```
|
||||||
|
|
||||||
|
### "unable to open database file"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
chown www-data:posterg /var/www/posterg/storage/test.db
|
||||||
|
chmod 660 /var/www/posterg/storage/test.db
|
||||||
|
chmod 775 /var/www/posterg/storage/
|
||||||
|
```
|
||||||
|
|
||||||
|
### "attempt to write a readonly database"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
chmod 775 /var/www/posterg/storage/
|
||||||
|
rm -f /var/www/posterg/storage/test.db-*
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Important Notes
|
||||||
|
|
||||||
|
### Production Safety
|
||||||
|
|
||||||
|
`just deploy` **excludes all `.db` files** by default. Only `just deploy-db` uploads the test database.
|
||||||
|
|
||||||
|
### Backup Production Database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh posterg
|
||||||
|
cp /var/www/posterg/storage/posterg.db /var/www/posterg/storage/posterg.db.backup.$(date +%Y%m%d)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Related Commands
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `just init-db` | Create empty test database |
|
||||||
|
| `just fixtures` | Create test database with sample data |
|
||||||
|
| `just deploy-db` | Deploy test database to server |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Deployment Checklist
|
||||||
|
|
||||||
|
After running `just deploy-db`, verify:
|
||||||
|
|
||||||
|
- [ ] Database file exists: `ssh posterg "ls -la /var/www/posterg/storage/test.db"`
|
||||||
|
- [ ] Correct permissions: `-rw-rw---- www-data posterg`
|
||||||
|
- [ ] Site loads: Visit https://posterg.erg.be/
|
||||||
|
- [ ] No errors in logs: `ssh posterg "tail /var/log/nginx/posterg_error.log"`
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Manage admin users for Post-ERG nginx basic authentication
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Colors
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
PASSWORD_FILE="/etc/nginx/.htpasswd-posterg"
|
|
||||||
|
|
||||||
# Check if running as root
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
|
||||||
echo -e "${RED}Error: This script must be run as root (use sudo)${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if htpasswd is available
|
|
||||||
if ! command -v htpasswd &> /dev/null; then
|
|
||||||
echo -e "${YELLOW}Installing apache2-utils...${NC}"
|
|
||||||
apt-get update -qq
|
|
||||||
apt-get install -y apache2-utils
|
|
||||||
fi
|
|
||||||
|
|
||||||
show_menu() {
|
|
||||||
echo ""
|
|
||||||
echo -e "${BLUE}════════════════════════════════════════${NC}"
|
|
||||||
echo -e "${BLUE} Post-ERG Admin User Management${NC}"
|
|
||||||
echo -e "${BLUE}════════════════════════════════════════${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "1. List all users"
|
|
||||||
echo "2. Add new user"
|
|
||||||
echo "3. Change user password"
|
|
||||||
echo "4. Delete user"
|
|
||||||
echo "5. Reset all (create new password file)"
|
|
||||||
echo "6. Exit"
|
|
||||||
echo ""
|
|
||||||
echo -n "Choose an option [1-6]: "
|
|
||||||
}
|
|
||||||
|
|
||||||
list_users() {
|
|
||||||
echo ""
|
|
||||||
if [ ! -f "$PASSWORD_FILE" ]; then
|
|
||||||
echo -e "${YELLOW}No password file found.${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}Current admin users:${NC}"
|
|
||||||
echo "────────────────────────"
|
|
||||||
cut -d: -f1 "$PASSWORD_FILE" | nl
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
add_user() {
|
|
||||||
echo ""
|
|
||||||
echo -n "Enter new username: "
|
|
||||||
read -r USERNAME
|
|
||||||
|
|
||||||
if [ -z "$USERNAME" ]; then
|
|
||||||
echo -e "${RED}Username cannot be empty${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if user already exists
|
|
||||||
if [ -f "$PASSWORD_FILE" ] && grep -q "^${USERNAME}:" "$PASSWORD_FILE"; then
|
|
||||||
echo -e "${YELLOW}User '$USERNAME' already exists. Use option 3 to change password.${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Add user (use -c only if file doesn't exist)
|
|
||||||
if [ ! -f "$PASSWORD_FILE" ]; then
|
|
||||||
htpasswd -c "$PASSWORD_FILE" "$USERNAME"
|
|
||||||
else
|
|
||||||
htpasswd "$PASSWORD_FILE" "$USERNAME"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}✓ User '$USERNAME' added successfully${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
change_password() {
|
|
||||||
list_users
|
|
||||||
echo -n "Enter username to change password: "
|
|
||||||
read -r USERNAME
|
|
||||||
|
|
||||||
if [ -z "$USERNAME" ]; then
|
|
||||||
echo -e "${RED}Username cannot be empty${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$PASSWORD_FILE" ]; then
|
|
||||||
echo -e "${RED}Password file not found${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -q "^${USERNAME}:" "$PASSWORD_FILE"; then
|
|
||||||
echo -e "${RED}User '$USERNAME' not found${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
htpasswd "$PASSWORD_FILE" "$USERNAME"
|
|
||||||
echo -e "${GREEN}✓ Password changed for user '$USERNAME'${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
delete_user() {
|
|
||||||
list_users
|
|
||||||
echo -n "Enter username to delete: "
|
|
||||||
read -r USERNAME
|
|
||||||
|
|
||||||
if [ -z "$USERNAME" ]; then
|
|
||||||
echo -e "${RED}Username cannot be empty${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$PASSWORD_FILE" ]; then
|
|
||||||
echo -e "${RED}Password file not found${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -q "^${USERNAME}:" "$PASSWORD_FILE"; then
|
|
||||||
echo -e "${RED}User '$USERNAME' not found${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -n "Are you sure you want to delete user '$USERNAME'? [y/N] "
|
|
||||||
read -r CONFIRM
|
|
||||||
|
|
||||||
if [ "$CONFIRM" = "y" ] || [ "$CONFIRM" = "Y" ]; then
|
|
||||||
htpasswd -D "$PASSWORD_FILE" "$USERNAME"
|
|
||||||
echo -e "${GREEN}✓ User '$USERNAME' deleted${NC}"
|
|
||||||
else
|
|
||||||
echo "Cancelled"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_all() {
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}WARNING: This will delete ALL existing users!${NC}"
|
|
||||||
echo -n "Are you sure? [y/N] "
|
|
||||||
read -r CONFIRM
|
|
||||||
|
|
||||||
if [ "$CONFIRM" != "y" ] && [ "$CONFIRM" != "Y" ]; then
|
|
||||||
echo "Cancelled"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Backup existing file
|
|
||||||
if [ -f "$PASSWORD_FILE" ]; then
|
|
||||||
BACKUP="${PASSWORD_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
|
|
||||||
cp "$PASSWORD_FILE" "$BACKUP"
|
|
||||||
echo -e "${GREEN}✓ Backed up to: $BACKUP${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo -n "Enter new username: "
|
|
||||||
read -r USERNAME
|
|
||||||
|
|
||||||
if [ -z "$USERNAME" ]; then
|
|
||||||
echo -e "${RED}Username cannot be empty${NC}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
htpasswd -c "$PASSWORD_FILE" "$USERNAME"
|
|
||||||
echo -e "${GREEN}✓ Password file reset with user '$USERNAME'${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main loop
|
|
||||||
while true; do
|
|
||||||
show_menu
|
|
||||||
read -r CHOICE
|
|
||||||
|
|
||||||
case $CHOICE in
|
|
||||||
1)
|
|
||||||
list_users
|
|
||||||
;;
|
|
||||||
2)
|
|
||||||
add_user
|
|
||||||
;;
|
|
||||||
3)
|
|
||||||
change_password
|
|
||||||
;;
|
|
||||||
4)
|
|
||||||
delete_user
|
|
||||||
;;
|
|
||||||
5)
|
|
||||||
reset_all
|
|
||||||
;;
|
|
||||||
6)
|
|
||||||
echo ""
|
|
||||||
echo "Goodbye!"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "${RED}Invalid option${NC}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
Reference in New Issue
Block a user