Consolidate nginx docs and scripts, update paths

This commit is contained in:
Pontoporeia
2026-04-15 10:58:49 +02:00
parent 3cd96ed28a
commit 507f3eb704
23 changed files with 645 additions and 2256 deletions

View File

@@ -34,7 +34,9 @@ posterg/
│ ├── deploy-server.sh # Run on server with sudo to apply nginx config
│ └── manage-admin-users.sh # Run on server with sudo to manage htpasswd
└── 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
@@ -73,19 +75,19 @@ sudo chmod 775 /var/www/posterg
exit
```
Then deploy once, copy nginx config, and apply:
Then deploy once and apply nginx config:
```bash
just deploy
rsync -v nginx/posterg.conf posterg:/tmp/posterg.conf
ssh posterg "sudo bash /var/www/posterg/scripts/deploy-server.sh"
ssh posterg "sudo systemctl reload nginx"
just deploy-nginx
```
### Admin users (htpasswd)
```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

134
SETUP.md Normal file
View 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
View File

@@ -1,4 +1,9 @@
# TODO
- [x] Remove random HSL gradients from homepage cards and use header's background gradient
- [ ] Review other gradient usages (check if any leftover random hue generation anywhere)
- [x] Analyze nginx/docs and nginx/scripts for deduplication opportunities
- [x] Deduplicate nginx documentation files (removed DEPLOYMENT_COMPLETE.md, DEPLOY_NOW.md)
- [x] Remove duplicate scripts (deploy-production.sh, deploy-production-new.sh, manage-admin-users.sh)
- [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/)

View File

@@ -62,6 +62,15 @@ setup-server:
@echo " sudo DEPLOY_USER=\$USER bash /tmp/setup-server.sh"
@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')]
deploy-nginx:
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 ""
@echo " sudo bash /tmp/deploy-server.sh"
@echo " sudo systemctl reload nginx"
@echo ""
[group('deploy')]

View File

@@ -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** 🎉

View File

@@ -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
```

View File

@@ -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
```

View File

@@ -1,17 +1,26 @@
# 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
- **`posterg.conf`** - Complete nginx configuration file
- **`setup-password.sh`** - Script to create admin passwords
- **`SETUP.md`** - Detailed setup instructions
- **`QUICK_REFERENCE.md`** - Command reference and troubleshooting
- **`scripts/`** - Server setup scripts
- `setup-password.sh` - Create admin passwords
- `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
### 1. Deploy nginx configuration (automated)
### Deploy nginx configuration
```bash
# From your local machine
@@ -19,38 +28,37 @@ just deploy-nginx
# Then on the server:
ssh posterg
sudo bash /tmp/deploy-production.sh
sudo bash /tmp/deploy-server.sh
sudo systemctl reload nginx
```
The deployment script will:
- ✅ Fix file permissions (posterg group)
- ✅ Set up admin password (if needed)
- ✅ Fix file permissions (www-data:posterg)
- ✅ Install nginx configuration
- ✅ Test and reload nginx
- ✅ Verify PHP-FPM is running
### 2. SSL/TLS
### Manage admin users
SSL/TLS is handled by the upstream reverse proxy and is already working.
No additional SSL setup is needed on this server.
```bash
just manage-admin-users
ssh posterg "sudo bash /tmp/manage-admin-users.sh"
```
## 🔒 Security Features
### Admin Panel Protection
- **Password required** for `/formulaire/` (admin panel)
- **Password required** for `/admin/`
- HTTP Basic Authentication
- Rate limited: 10 requests/minute
### File Access Protection
- Database files (`.db`) - **BLOCKED**
- Sensitive files (`.md`, `.sql`, `.env`) - **BLOCKED**
- `/src` directory (PHP source) - **BLOCKED**
- `/templates` directory (PHP templates) - **BLOCKED**
- `/config` directory (configuration) - **BLOCKED**
- `/storage` directory (databases) - **BLOCKED**
- `/tests` directory - **BLOCKED**
- `/scripts` directory - **BLOCKED**
- `/docs` directory - **BLOCKED**
- `/src` directory - **BLOCKED**
- `/templates` directory - **BLOCKED**
- `/config` directory - **BLOCKED**
- `/storage` directory - **BLOCKED**
- Hidden files (`.git`, etc.) - **BLOCKED**
### Rate Limiting
@@ -61,45 +69,25 @@ No additional SSL setup is needed on this server.
### Security Headers
- ✅ X-Frame-Options (clickjacking protection)
- ✅ X-Content-Type-Options (MIME sniffing protection)
- ✅ X-XSS-Protection (XSS filter)
- ✅ Strict-Transport-Security (force HTTPS)
- ✅ Referrer-Policy (referrer control)
- ✅ Permissions-Policy (disable browser features)
### SSL/TLS
- TLS 1.2 and 1.3 only
- Strong cipher suites
- OCSP stapling
- HSTS enabled
## 📚 Documentation
- **[SETUP.md](SETUP.md)** - Complete setup guide
- Installation steps
- Configuration details
- Testing procedures
- Troubleshooting
- Performance tuning
- Security checklist
- **[QUICK_REFERENCE.md](QUICK_REFERENCE.md)** - Command reference
- Common operations
- Password management
- Nginx control
- Log viewing
- Testing commands
- Troubleshooting
- **[docs/PRODUCTION_DEPLOYMENT.md](docs/PRODUCTION_DEPLOYMENT.md)** - Complete deployment guide
- **[docs/QUICK_REFERENCE.md](docs/QUICK_REFERENCE.md)** - Command reference and troubleshooting
- **[docs/ADMIN_USERS.md](docs/ADMIN_USERS.md)** - Admin user management
- **[docs/SECURITY_HEADERS.md](docs/SECURITY_HEADERS.md)** - Security headers reference
## 🧪 Testing
Test your configuration:
```bash
# Test admin authentication
curl -I https://posterg.erg.be/formulaire/
curl -I https://posterg.erg.be/admin/
# Test file protection
curl -I https://posterg.erg.be/storage/posterg.db
curl -I https://posterg.erg.be/storage/test.db
# Test security headers
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
```bash
# Reset password
sudo htpasswd /etc/nginx/.htpasswd-posterg admin
```
### 502 Bad Gateway
```bash
# Check PHP-FPM
sudo systemctl status php8.2-fpm
sudo systemctl restart php8.2-fpm
sudo systemctl status php8.4-fpm
sudo systemctl restart php8.4-fpm
```
### Configuration errors
```bash
# Test and show errors
sudo nginx -t
```
## 📊 Monitoring
```bash
# Watch access logs
# Watch logs
sudo tail -f /var/log/nginx/posterg_access.log
# Watch error logs
sudo tail -f /var/log/nginx/posterg_error.log
# Check nginx status
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`

View File

@@ -1,369 +1,127 @@
# 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
- Ubuntu/Debian server with root access
- Nginx installed
- PHP-FPM installed (PHP 8.2 or later)
- PHP-FPM installed (PHP 8.4)
- 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
```bash
# Install nginx and apache2-utils (for htpasswd)
sudo apt update
sudo apt install nginx apache2-utils php8.2-fpm
# Install SSL certificate tool (optional, for HTTPS)
sudo apt install certbot python3-certbot-nginx
sudo apt install nginx apache2-utils php8.4-fpm
```
### 2. Create Password File for Admin Panel
Create a password-protected admin area:
### 2. Create Admin Password
```bash
# Create htpasswd file
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
```bash
# Copy the config file
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/
# Remove default site (optional)
sudo rm /etc/nginx/sites-enabled/default
sudo rm -f /etc/nginx/sites-enabled/default
```
### 4. Update Domain Name
Edit the configuration to use your domain:
### 4. Test and Reload
```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
# If test passes, reload nginx
sudo systemctl reload nginx
# Check nginx status
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
### Test Admin Password Protection
### Test Admin Authentication
```bash
# Should prompt for password
curl -I https://posterg.erg.be/formulaire/
# Should return 401
curl -I https://posterg.erg.be/admin/
# 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
# Make multiple rapid requests (should get 429 Too Many Requests after limit)
for i in {1..50}; do curl -I https://posterg.erg.be/ 2>&1 | grep HTTP; done
```
### 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
# Should return 403
curl -I https://posterg.erg.be/storage/test.db
curl -I https://posterg.erg.be/src/Database.php
```
### Test Security Headers
```bash
# Check security headers
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
curl -I https://posterg.erg.be/ | grep -E "X-|Strict-Transport"
```
## Troubleshooting
### "403 Forbidden" on admin panel
- Check htpasswd file exists: `ls -l /etc/nginx/.htpasswd-posterg`
- Check file permissions: `sudo chmod 644 /etc/nginx/.htpasswd-posterg`
- Check credentials are correct
### 403 Forbidden on admin
```bash
sudo ls -l /etc/nginx/.htpasswd-posterg
sudo chmod 644 /etc/nginx/.htpasswd-posterg
```
### "502 Bad Gateway"
- Check PHP-FPM is running: `sudo systemctl status php8.2-fpm`
- Check socket path in nginx config matches PHP-FPM config
- Check PHP-FPM logs: `sudo tail /var/log/php8.2-fpm.log`
### 502 Bad Gateway
```bash
sudo systemctl status php8.4-fpm
sudo systemctl restart php8.4-fpm
```
### "File not found" errors
- Check root path in nginx config
- Check file permissions
- Check PHP-FPM open_basedir setting
### Rate limiting too strict
- Adjust `rate=` values in nginx config
- Adjust `burst=` values for each location
### Configuration errors
```bash
sudo nginx -t
```
## Maintenance
### Change Admin Password
```bash
# Change password for existing user
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
# Manual renewal
sudo certbot renew
# Check expiry
sudo certbot certificates
sudo nginx -t && sudo systemctl reload nginx
```
### Update Configuration
## See Also
```bash
# After modifying config file
sudo nginx -t
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.
- **[docs/PRODUCTION_DEPLOYMENT.md](docs/PRODUCTION_DEPLOYMENT.md)** - Detailed deployment
- **[docs/QUICK_REFERENCE.md](docs/QUICK_REFERENCE.md)** - Command reference
- **[docs/ADMIN_USERS.md](docs/ADMIN_USERS.md)** - User management

View File

@@ -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! 🚀

View File

@@ -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)"

View File

@@ -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 ""

View File

@@ -9,6 +9,10 @@ Quick guide to manage admin users for the Post-ERG admin panel.
### Interactive Menu (Recommended)
```bash
# From your local machine
just manage-admin-users
# Then on the server
ssh posterg
sudo bash /tmp/manage-admin-users.sh
```
@@ -71,10 +75,10 @@ To upload the interactive management script to the server:
```bash
# From your local machine
just deploy-admin-tools
just manage-admin-users
# 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
After deployment, your admin panel has:
- **URL:** https://posterg.erg.be/formulaire/
- **URL:** https://posterg.erg.be/admin/
- **Current user:** `test_posterg_22@`
- **Password:** Set during initial deployment
@@ -127,7 +131,7 @@ sudo htpasswd /etc/nginx/.htpasswd-posterg admin2
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
@@ -145,11 +149,11 @@ After changing users/passwords:
```bash
# Test that password is required
curl -I https://posterg.erg.be/formulaire/
curl -I https://posterg.erg.be/admin/
# Should return: 401 Unauthorized
# 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
```
@@ -193,7 +197,7 @@ username:$apr1$encrypted_password_hash
```bash
# Check who's accessing the admin panel
ssh posterg
sudo grep "formulaire" /var/log/nginx/posterg_access.log
sudo grep "admin" /var/log/nginx/posterg_access.log
```
5. **Backup Password File**
@@ -263,7 +267,7 @@ No action needed! Changes to the password file take effect immediately.
You can verify with:
```bash
curl -u username:password https://posterg.erg.be/formulaire/
curl -u username:password https://posterg.erg.be/admin/
```
---

View File

@@ -1,9 +1,11 @@
# `.htaccess` → nginx migration (item #6)
# `.htaccess` → nginx migration
> **Problem:** `public/admin/.htaccess` contained Apache-specific security
> directives that nginx **silently ignores**. None of the rules were active
> in production.
> **Status:** Migrated into `nginx/posterg.conf`
---
## Rules migrated into `nginx/posterg.conf`

View File

@@ -11,7 +11,7 @@ The admin panel uses **two independent authentication layers** with a single UX
| Layer | Mechanism | Configured by |
|-------|-----------|---------------|
| **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
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 |
|------|--------|
| `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.example.php` | New — example / template |
| `config/bootstrap.php` | Load credentials on startup |

View 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

View File

@@ -3,22 +3,13 @@
## Setup Commands
```bash
# Make setup script executable
chmod +x nginx/setup-password.sh
# Run password setup (as root)
sudo ./nginx/setup-password.sh
# Copy nginx config
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 rm -f /etc/nginx/sites-enabled/default
# Test configuration
# Test and reload
sudo nginx -t
# Reload nginx
sudo systemctl reload nginx
```
@@ -27,6 +18,10 @@ sudo systemctl reload nginx
### Password Management
```bash
# Interactive menu (recommended)
sudo bash /tmp/manage-admin-users.sh
# Or manual commands:
# Add new user
sudo htpasswd /etc/nginx/.htpasswd-posterg username
@@ -103,10 +98,10 @@ sudo certbot renew --dry-run
```bash
# Should require password (returns 401)
curl -I https://posterg.erg.be/formulaire/
curl -I https://posterg.erg.be/admin/
# With authentication
curl -u admin:password https://posterg.erg.be/formulaire/
curl -u admin:password https://posterg.erg.be/admin/
```
### Test Rate Limiting
@@ -173,7 +168,7 @@ sudo tail -50 /var/log/nginx/error.log
```bash
# Disable password protection temporarily
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_user_file /etc/nginx/.htpasswd-posterg;

View File

@@ -18,6 +18,7 @@
These were previously declared in `public/admin/.htaccess` as Apache
`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.
## Intentionally omitted headers

View 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"`

View File

@@ -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