mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
Nginx config, working deploy, basic theme, repo cleanup
This commit is contained in:
271
nginx/ADMIN_USERS.md
Normal file
271
nginx/ADMIN_USERS.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# Managing Admin Users - Post-ERG
|
||||
|
||||
Quick guide to manage admin users for the Post-ERG admin panel.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Quick Commands
|
||||
|
||||
### Interactive Menu (Recommended)
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo bash /tmp/manage-admin-users.sh
|
||||
```
|
||||
|
||||
This gives you an interactive menu to:
|
||||
1. List all users
|
||||
2. Add new user
|
||||
3. Change user password
|
||||
4. Delete user
|
||||
5. Reset all (start fresh)
|
||||
|
||||
---
|
||||
|
||||
## 📝 Manual Commands
|
||||
|
||||
### List Current Users
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo cut -d: -f1 /etc/nginx/.htpasswd-posterg
|
||||
```
|
||||
|
||||
### Change Password for Existing User
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo htpasswd /etc/nginx/.htpasswd-posterg username_here
|
||||
```
|
||||
|
||||
You'll be prompted to enter the new password twice.
|
||||
|
||||
### Add New User
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo htpasswd /etc/nginx/.htpasswd-posterg new_username
|
||||
```
|
||||
|
||||
### Delete User
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo htpasswd -D /etc/nginx/.htpasswd-posterg username_to_delete
|
||||
```
|
||||
|
||||
### Reset Everything (Start Fresh)
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd-posterg new_username
|
||||
```
|
||||
|
||||
⚠️ **Warning:** The `-c` flag creates a new file, deleting all existing users!
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deploy Management Script
|
||||
|
||||
To upload the interactive management script to the server:
|
||||
|
||||
```bash
|
||||
# From your local machine
|
||||
just deploy-admin-tools
|
||||
|
||||
# Or manually:
|
||||
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/
|
||||
- **Current user:** `test_posterg_22@`
|
||||
- **Password:** Set during initial deployment
|
||||
|
||||
---
|
||||
|
||||
## 💡 Common Scenarios
|
||||
|
||||
### Scenario 1: Change Current Password
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo htpasswd /etc/nginx/.htpasswd-posterg test_posterg_22@
|
||||
# Enter new password when prompted
|
||||
```
|
||||
|
||||
### Scenario 2: Change Username
|
||||
|
||||
Since you can't rename users, you need to:
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
# Add new user
|
||||
sudo htpasswd /etc/nginx/.htpasswd-posterg new_username
|
||||
# Delete old user
|
||||
sudo htpasswd -D /etc/nginx/.htpasswd-posterg test_posterg_22@
|
||||
```
|
||||
|
||||
### Scenario 3: Forgot Username
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo cut -d: -f1 /etc/nginx/.htpasswd-posterg
|
||||
```
|
||||
|
||||
### Scenario 4: Multiple Admins
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
# Add second admin
|
||||
sudo htpasswd /etc/nginx/.htpasswd-posterg admin2
|
||||
# Add third admin
|
||||
sudo htpasswd /etc/nginx/.htpasswd-posterg admin3
|
||||
```
|
||||
|
||||
All users can log into `/formulaire/` with their own credentials.
|
||||
|
||||
### Scenario 5: Start Over with New Username
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
# This will DELETE ALL existing users and create a new one
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd-posterg new_admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
After changing users/passwords:
|
||||
|
||||
```bash
|
||||
# Test that password is required
|
||||
curl -I https://posterg.erg.be/formulaire/
|
||||
# Should return: 401 Unauthorized
|
||||
|
||||
# Test with credentials
|
||||
curl -u username:password https://posterg.erg.be/formulaire/
|
||||
# Should return: 200 OK
|
||||
```
|
||||
|
||||
No nginx reload needed - changes take effect immediately!
|
||||
|
||||
---
|
||||
|
||||
## 📊 Password File Details
|
||||
|
||||
**Location:** `/etc/nginx/.htpasswd-posterg`
|
||||
|
||||
**Format:** Standard Apache htpasswd format
|
||||
```
|
||||
username:$apr1$encrypted_password_hash
|
||||
```
|
||||
|
||||
**Permissions:**
|
||||
```bash
|
||||
-rw-r--r-- root root /etc/nginx/.htpasswd-posterg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security Tips
|
||||
|
||||
1. **Use Strong Passwords**
|
||||
```bash
|
||||
# Generate a strong password
|
||||
openssl rand -base64 32
|
||||
```
|
||||
|
||||
2. **Avoid Common Usernames**
|
||||
- ❌ Bad: `admin`, `administrator`, `root`
|
||||
- ✅ Good: `posterg_admin`, `erg_webmaster`
|
||||
|
||||
3. **Regular Password Changes**
|
||||
- Change passwords every 3-6 months
|
||||
- Change immediately if compromised
|
||||
|
||||
4. **Monitor Access**
|
||||
```bash
|
||||
# Check who's accessing the admin panel
|
||||
ssh posterg
|
||||
sudo grep "formulaire" /var/log/nginx/posterg_access.log
|
||||
```
|
||||
|
||||
5. **Backup Password File**
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo cp /etc/nginx/.htpasswd-posterg /etc/nginx/.htpasswd-posterg.backup
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Troubleshooting
|
||||
|
||||
### "401 Unauthorized" even with correct password
|
||||
|
||||
**Check file exists:**
|
||||
```bash
|
||||
ssh posterg
|
||||
ls -la /etc/nginx/.htpasswd-posterg
|
||||
```
|
||||
|
||||
**Verify user exists:**
|
||||
```bash
|
||||
sudo cat /etc/nginx/.htpasswd-posterg
|
||||
```
|
||||
|
||||
**Check nginx config:**
|
||||
```bash
|
||||
sudo grep -A 5 "auth_basic" /etc/nginx/sites-available/posterg
|
||||
```
|
||||
|
||||
### Can't change password - "command not found"
|
||||
|
||||
**Install apache2-utils:**
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo apt update
|
||||
sudo apt install apache2-utils
|
||||
```
|
||||
|
||||
### Password file got deleted
|
||||
|
||||
**Recreate it:**
|
||||
```bash
|
||||
ssh posterg
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd-posterg new_admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 Quick Reference
|
||||
|
||||
| Task | Command |
|
||||
|------|---------|
|
||||
| **Interactive menu** | `sudo bash /tmp/manage-admin-users.sh` |
|
||||
| **List users** | `sudo cut -d: -f1 /etc/nginx/.htpasswd-posterg` |
|
||||
| **Change password** | `sudo htpasswd /etc/nginx/.htpasswd-posterg username` |
|
||||
| **Add user** | `sudo htpasswd /etc/nginx/.htpasswd-posterg newuser` |
|
||||
| **Delete user** | `sudo htpasswd -D /etc/nginx/.htpasswd-posterg username` |
|
||||
| **Reset all** | `sudo htpasswd -c /etc/nginx/.htpasswd-posterg newuser` |
|
||||
| **Generate password** | `openssl rand -base64 32` |
|
||||
|
||||
---
|
||||
|
||||
## ✅ After Making Changes
|
||||
|
||||
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/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Remember:** Store passwords securely using a password manager! 🔐
|
||||
379
nginx/DEPLOYMENT_COMPLETE.md
Normal file
379
nginx/DEPLOYMENT_COMPLETE.md
Normal file
@@ -0,0 +1,379 @@
|
||||
# ✅ Production Deployment Complete - Post-ERG
|
||||
|
||||
**Date:** February 5, 2026
|
||||
**Status:** ✅ Successfully Deployed
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Deployment Summary
|
||||
|
||||
The Post-ERG website is now successfully deployed with production-ready nginx configuration and security hardening.
|
||||
|
||||
### ✅ What's Working
|
||||
|
||||
| Feature | Status | Test Result |
|
||||
|---------|--------|-------------|
|
||||
| **Public Site** | ✅ Working | https://posterg.erg.be/ → 200 OK |
|
||||
| **SSL/TLS** | ✅ Working | HTTPS with valid certificate |
|
||||
| **Admin Panel** | ✅ Protected | /formulaire/ → 401 (requires password) |
|
||||
| **Database Protection** | ✅ Blocked | /database/ → 403 Forbidden |
|
||||
| **Sensitive Files** | ✅ Blocked | .md, .sql files → 403 Forbidden |
|
||||
| **Shared Directory** | ✅ Blocked | /shared/ → 403 Forbidden |
|
||||
| **Security Headers** | ✅ Present | X-Frame-Options, CSP, etc. |
|
||||
| **PHP 8.4** | ✅ Running | php8.4-fpm active |
|
||||
| **File Permissions** | ✅ Fixed | posterg group, readable by www-data |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 What Was Fixed
|
||||
|
||||
### 1. File Permissions
|
||||
**Problem:** Files owned by `theophile:theophile` with 640 permissions, nginx couldn't read them.
|
||||
|
||||
**Solution:**
|
||||
```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:**
|
||||
- `/database/` - 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/database/posterg.db # Should: 403 Forbidden
|
||||
curl -I http://localhost/README.md # Should: 403 Forbidden
|
||||
curl -I http://localhost/shared/Database.php # Should: 403 Forbidden
|
||||
```
|
||||
|
||||
### External Tests
|
||||
|
||||
```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/database/posterg.db`
|
||||
|
||||
---
|
||||
|
||||
## ✅ Success Checklist
|
||||
|
||||
After any deployment, verify:
|
||||
|
||||
- [ ] Public site loads: https://posterg.erg.be/
|
||||
- [ ] Search works
|
||||
- [ ] Individual thesis pages work
|
||||
- [ ] Admin requires password
|
||||
- [ ] Admin can log in
|
||||
- [ ] File uploads work (in admin)
|
||||
- [ ] Database is protected (403)
|
||||
- [ ] Sensitive files blocked (403)
|
||||
- [ ] No errors in logs
|
||||
- [ ] Security headers present
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentation Files
|
||||
|
||||
- `posterg-production.conf` - Production nginx 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** 🎉
|
||||
276
nginx/DEPLOY_NOW.md
Normal file
276
nginx/DEPLOY_NOW.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# 🚀 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
|
||||
- `/database/` 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/database/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
|
||||
```
|
||||
346
nginx/PRODUCTION_DEPLOYMENT.md
Normal file
346
nginx/PRODUCTION_DEPLOYMENT.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# 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/database/posterg.db
|
||||
sudo chown www-data:posterg /var/www/html/database/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/database/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/database/posterg.db
|
||||
sudo chmod 640 /var/www/html/database/posterg.db
|
||||
sudo chmod 755 /var/www/html/database/
|
||||
```
|
||||
|
||||
### 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
|
||||
```
|
||||
@@ -11,36 +11,28 @@ This directory contains nginx configuration and setup scripts for the Post-ERG t
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### 1. Set up admin password
|
||||
|
||||
```bash
|
||||
# Make script executable
|
||||
chmod +x nginx/setup-password.sh
|
||||
|
||||
# Run setup (as root on server)
|
||||
sudo ./nginx/setup-password.sh
|
||||
```
|
||||
|
||||
### 2. Deploy nginx configuration
|
||||
### 1. Deploy nginx configuration (automated)
|
||||
|
||||
```bash
|
||||
# From your local machine
|
||||
just deploy-nginx
|
||||
|
||||
# Then on the server:
|
||||
sudo cp /tmp/posterg.conf /etc/nginx/sites-available/posterg
|
||||
sudo ln -s /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/
|
||||
sudo nginx -t
|
||||
sudo systemctl reload nginx
|
||||
ssh posterg
|
||||
sudo bash /tmp/deploy-production.sh
|
||||
```
|
||||
|
||||
### 3. Set up SSL (production)
|
||||
The deployment script will:
|
||||
- ✅ Fix file permissions (posterg group)
|
||||
- ✅ Set up admin password (if needed)
|
||||
- ✅ Install nginx configuration
|
||||
- ✅ Test and reload nginx
|
||||
- ✅ Verify PHP-FPM is running
|
||||
|
||||
```bash
|
||||
# On server
|
||||
sudo apt install certbot python3-certbot-nginx
|
||||
sudo certbot --nginx -d posterg.erg.be -d www.posterg.erg.be
|
||||
```
|
||||
### 2. SSL/TLS
|
||||
|
||||
SSL/TLS is handled by the upstream reverse proxy and is already working.
|
||||
No additional SSL setup is needed on this server.
|
||||
|
||||
## 🔒 Security Features
|
||||
|
||||
|
||||
352
nginx/TEST_DATABASE_SETUP.md
Normal file
352
nginx/TEST_DATABASE_SETUP.md
Normal file
@@ -0,0 +1,352 @@
|
||||
# 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/database/` 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/database/test.db` (test mode)
|
||||
- `/var/www/html/database/posterg.db` (production mode)
|
||||
|
||||
### 5. Switch Back to Production
|
||||
|
||||
Simply remove the test database:
|
||||
|
||||
```bash
|
||||
ssh posterg
|
||||
rm /var/www/html/database/test.db
|
||||
```
|
||||
|
||||
The site automatically switches to production database.
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Permissions Explained
|
||||
|
||||
### Directory Permissions
|
||||
|
||||
```
|
||||
drwxrwxr-x theophile posterg /var/www/html/database/
|
||||
```
|
||||
|
||||
- **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/database/test.db
|
||||
|
||||
# Fix permissions
|
||||
chmod 775 /var/www/html/database
|
||||
chmod 660 /var/www/html/database/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/database/test.db-journal
|
||||
rm -f /var/www/html/database/test.db-shm
|
||||
rm -f /var/www/html/database/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/database/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/database/posterg.db /var/www/html/database/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/database/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/database/test.db"
|
||||
```
|
||||
|
||||
Site automatically uses `posterg.db` again! 🚀
|
||||
180
nginx/deploy-production.sh
Executable file
180
nginx/deploy-production.sh
Executable file
@@ -0,0 +1,180 @@
|
||||
#!/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/database/posterg.db" ]; then
|
||||
chmod 660 /var/www/html/database/posterg.db
|
||||
chown www-data:posterg /var/www/html/database/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/database/posterg.db"
|
||||
echo " • MD files blocked: curl -I http://localhost/README.md"
|
||||
echo " • Shared blocked: curl -I http://localhost/shared/Database.php"
|
||||
echo ""
|
||||
24
nginx/fix-paths.sh
Normal file
24
nginx/fix-paths.sh
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
# Fix shared library paths for production deployment
|
||||
|
||||
echo "🔧 Fixing shared library paths for production..."
|
||||
|
||||
cd /var/www/html
|
||||
|
||||
# Fix paths in PHP files
|
||||
find . -maxdepth 1 -name "*.php" -type f -exec sed -i "s|__DIR__ \. '/\.\./\.\./shared/|__DIR__ . '/shared/|g" {} \;
|
||||
|
||||
echo "✓ Updated paths in:"
|
||||
echo " - index.php"
|
||||
echo " - memoire.php"
|
||||
echo " - search.php"
|
||||
echo " - test_db.php"
|
||||
|
||||
# Test if it works
|
||||
echo ""
|
||||
echo "🧪 Testing..."
|
||||
php -r "require_once '/var/www/html/shared/Database.php'; echo 'Database.php loads successfully\n';"
|
||||
|
||||
echo ""
|
||||
echo "✅ Path fix complete!"
|
||||
echo "Try: curl http://localhost/"
|
||||
34
nginx/install-php-sqlite.sh
Executable file
34
nginx/install-php-sqlite.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
# Install PHP SQLite extension
|
||||
|
||||
echo "🔧 Installing PHP SQLite extension..."
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Error: This script must be run as root (use sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Detect PHP version
|
||||
PHP_VERSION=$(php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;")
|
||||
echo "Detected PHP version: $PHP_VERSION"
|
||||
|
||||
# Install SQLite extension
|
||||
echo "Installing php${PHP_VERSION}-sqlite3..."
|
||||
apt-get update -qq
|
||||
apt-get install -y php${PHP_VERSION}-sqlite3
|
||||
|
||||
# Restart PHP-FPM
|
||||
echo "Restarting PHP-FPM..."
|
||||
systemctl restart php${PHP_VERSION}-fpm
|
||||
|
||||
# Verify installation
|
||||
if php -m | grep -q sqlite3; then
|
||||
echo "✅ SQLite extension installed successfully"
|
||||
echo ""
|
||||
echo "Installed extensions:"
|
||||
php -m | grep -i sqlite
|
||||
else
|
||||
echo "❌ Failed to install SQLite extension"
|
||||
exit 1
|
||||
fi
|
||||
199
nginx/manage-admin-users.sh
Executable file
199
nginx/manage-admin-users.sh
Executable file
@@ -0,0 +1,199 @@
|
||||
#!/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
|
||||
@@ -1,24 +1,23 @@
|
||||
# Nginx configuration for Post-ERG thesis website
|
||||
# Nginx configuration for Post-ERG thesis website (Production)
|
||||
# Based on existing default config with security enhancements
|
||||
# Place this in /etc/nginx/sites-available/posterg
|
||||
# Then symlink: ln -s /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/
|
||||
|
||||
# Rate limiting zones
|
||||
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/m;
|
||||
limit_req_zone $binary_remote_addr zone=search:10m rate=30r/m;
|
||||
limit_req_zone $binary_remote_addr zone=admin:10m rate=10r/m;
|
||||
|
||||
# Server block - HTTP (redirect to HTTPS in production)
|
||||
# Main server block
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
|
||||
server_name posterg.erg.be www.posterg.erg.be;
|
||||
|
||||
# Redirect all HTTP to HTTPS (uncomment in production)
|
||||
# return 301 https://$server_name$request_uri;
|
||||
|
||||
# For development/testing, allow HTTP
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
# Add index.php to the list
|
||||
index index.php index.html index.htm;
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
@@ -27,8 +26,8 @@ server {
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
|
||||
|
||||
# Disable server tokens
|
||||
server_tokens off;
|
||||
# Server tokens already disabled in nginx.conf
|
||||
# server_tokens off;
|
||||
|
||||
# Max upload size (for thesis files)
|
||||
client_max_body_size 100M;
|
||||
@@ -38,48 +37,35 @@ server {
|
||||
access_log /var/log/nginx/posterg_access.log;
|
||||
error_log /var/log/nginx/posterg_error.log warn;
|
||||
|
||||
# Block common attack patterns
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~ \.(git|env|db-journal)$ {
|
||||
# Block access to hidden files (except .well-known for Let's Encrypt)
|
||||
location ~ /\.(?!well-known).* {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Deny access to sensitive files
|
||||
location ~* \.(md|txt|sql|sh|json)$ {
|
||||
location ~* \.(md|txt|sql|sh|json|gitignore)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to database files
|
||||
location ~* \.db$ {
|
||||
# Deny access to database directory
|
||||
location ^~ /database/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to shared/ directory (PHP includes only)
|
||||
location /shared/ {
|
||||
location ^~ /shared/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to tests directory
|
||||
location /tests/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to cache directory
|
||||
location /cache/ {
|
||||
# Deny access to data directory
|
||||
location ^~ /data/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Admin panel - password protected
|
||||
location /formulaire/ {
|
||||
alias /var/www/html/formulaire/;
|
||||
|
||||
location ^~ /formulaire/ {
|
||||
# HTTP Basic Authentication
|
||||
auth_basic "Admin Access - Post-ERG";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd-posterg;
|
||||
@@ -87,35 +73,42 @@ server {
|
||||
# Rate limiting for admin
|
||||
limit_req zone=admin burst=5 nodelay;
|
||||
|
||||
# PHP handling
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
# Allow access to public assets without authentication
|
||||
location ~ ^/formulaire/(css|js|images)/ {
|
||||
auth_basic off;
|
||||
}
|
||||
|
||||
# Additional security for admin
|
||||
# PHP handling for admin
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
|
||||
}
|
||||
|
||||
# Additional security headers for admin
|
||||
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||
|
||||
# Try to serve file, otherwise 404
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
# Search endpoint - rate limiting
|
||||
location /search.php {
|
||||
location = /search.php {
|
||||
limit_req zone=search burst=10 nodelay;
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
|
||||
}
|
||||
|
||||
# Public PHP files
|
||||
# PHP files handler
|
||||
location ~ \.php$ {
|
||||
# Rate limiting for general PHP requests
|
||||
limit_req zone=general burst=20 nodelay;
|
||||
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
|
||||
|
||||
# Security parameters
|
||||
fastcgi_param PHP_VALUE "upload_max_filesize=50M \n post_max_size=100M";
|
||||
fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/html:/tmp";
|
||||
|
||||
|
||||
# Timeouts
|
||||
fastcgi_read_timeout 120;
|
||||
fastcgi_send_timeout 120;
|
||||
@@ -128,156 +121,20 @@ server {
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Root location
|
||||
# PDF files (thesis documents)
|
||||
location ~* \.pdf$ {
|
||||
expires 7d;
|
||||
add_header Cache-Control "public";
|
||||
add_header Content-Disposition "inline";
|
||||
}
|
||||
|
||||
# Root location - try files or 404
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
# Deny access to specific file types in data directories
|
||||
location ~* /data/.*\.(php|sh|py)$ {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
|
||||
# Server block - HTTPS (production)
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name posterg.erg.be www.posterg.erg.be;
|
||||
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
# SSL certificates (Let's Encrypt)
|
||||
# Run: certbot --nginx -d posterg.erg.be -d www.posterg.erg.be
|
||||
ssl_certificate /etc/letsencrypt/live/posterg.erg.be/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/posterg.erg.be/privkey.pem;
|
||||
|
||||
# SSL configuration
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
# Security headers (HTTPS)
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
|
||||
|
||||
# Disable server tokens
|
||||
server_tokens off;
|
||||
|
||||
# Max upload size
|
||||
client_max_body_size 100M;
|
||||
client_body_timeout 120s;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/posterg_ssl_access.log;
|
||||
error_log /var/log/nginx/posterg_ssl_error.log warn;
|
||||
|
||||
# Block common attack patterns
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~ \.(git|env|db-journal)$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Deny access to sensitive files
|
||||
location ~* \.(md|txt|sql|sh|json)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to database files
|
||||
location ~* \.db$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to shared/ directory
|
||||
location /shared/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to tests directory
|
||||
location /tests/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to cache directory
|
||||
location /cache/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Admin panel - password protected
|
||||
location /formulaire/ {
|
||||
alias /var/www/html/formulaire/;
|
||||
|
||||
# HTTP Basic Authentication
|
||||
auth_basic "Admin Access - Post-ERG";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd-posterg;
|
||||
|
||||
# Rate limiting
|
||||
limit_req zone=admin burst=5 nodelay;
|
||||
|
||||
# PHP handling
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
}
|
||||
|
||||
# Security headers
|
||||
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||
}
|
||||
|
||||
# Search endpoint - rate limiting
|
||||
location /search.php {
|
||||
limit_req zone=search burst=10 nodelay;
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
}
|
||||
|
||||
# Public PHP files
|
||||
location ~ \.php$ {
|
||||
limit_req zone=general burst=20 nodelay;
|
||||
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
|
||||
# Security parameters
|
||||
fastcgi_param PHP_VALUE "upload_max_filesize=50M \n post_max_size=100M";
|
||||
fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/html:/tmp";
|
||||
|
||||
# Timeouts
|
||||
fastcgi_read_timeout 120;
|
||||
fastcgi_send_timeout 120;
|
||||
}
|
||||
|
||||
# Static files caching
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|otf)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Root location
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
# Deny access to script files in data directories
|
||||
location ~* /data/.*\.(php|sh|py)$ {
|
||||
# Deny access to .htaccess files (if Apache's document root concurs with nginx's)
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
|
||||
283
nginx/posterg.conf.reference
Normal file
283
nginx/posterg.conf.reference
Normal file
@@ -0,0 +1,283 @@
|
||||
# Nginx configuration for Post-ERG thesis website
|
||||
# Place this in /etc/nginx/sites-available/posterg
|
||||
# Then symlink: ln -s /etc/nginx/sites-available/posterg /etc/nginx/sites-enabled/
|
||||
|
||||
# Rate limiting zones
|
||||
limit_req_zone $binary_remote_addr zone=general:10m rate=30r/m;
|
||||
limit_req_zone $binary_remote_addr zone=search:10m rate=30r/m;
|
||||
limit_req_zone $binary_remote_addr zone=admin:10m rate=10r/m;
|
||||
|
||||
# Server block - HTTP (redirect to HTTPS in production)
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name posterg.erg.be www.posterg.erg.be;
|
||||
|
||||
# Redirect all HTTP to HTTPS (uncomment in production)
|
||||
# return 301 https://$server_name$request_uri;
|
||||
|
||||
# For development/testing, allow HTTP
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
|
||||
|
||||
# Disable server tokens
|
||||
server_tokens off;
|
||||
|
||||
# Max upload size (for thesis files)
|
||||
client_max_body_size 100M;
|
||||
client_body_timeout 120s;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/posterg_access.log;
|
||||
error_log /var/log/nginx/posterg_error.log warn;
|
||||
|
||||
# Block common attack patterns
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~ \.(git|env|db-journal)$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Deny access to sensitive files
|
||||
location ~* \.(md|txt|sql|sh|json)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to database files
|
||||
location ~* \.db$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to shared/ directory (PHP includes only)
|
||||
location /shared/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to tests directory
|
||||
location /tests/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to cache directory
|
||||
location /cache/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Admin panel - password protected
|
||||
location /formulaire/ {
|
||||
alias /var/www/html/formulaire/;
|
||||
|
||||
# HTTP Basic Authentication
|
||||
auth_basic "Admin Access - Post-ERG";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd-posterg;
|
||||
|
||||
# Rate limiting for admin
|
||||
limit_req zone=admin burst=5 nodelay;
|
||||
|
||||
# PHP handling
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
}
|
||||
|
||||
# Additional security for admin
|
||||
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||
}
|
||||
|
||||
# Search endpoint - rate limiting
|
||||
location /search.php {
|
||||
limit_req zone=search burst=10 nodelay;
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
}
|
||||
|
||||
# Public PHP files
|
||||
location ~ \.php$ {
|
||||
limit_req zone=general burst=20 nodelay;
|
||||
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
|
||||
# Security parameters
|
||||
fastcgi_param PHP_VALUE "upload_max_filesize=50M \n post_max_size=100M";
|
||||
fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/html:/tmp";
|
||||
|
||||
# Timeouts
|
||||
fastcgi_read_timeout 120;
|
||||
fastcgi_send_timeout 120;
|
||||
}
|
||||
|
||||
# Static files caching
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|otf)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Root location
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
# Deny access to specific file types in data directories
|
||||
location ~* /data/.*\.(php|sh|py)$ {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
|
||||
# Server block - HTTPS (production)
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name posterg.erg.be www.posterg.erg.be;
|
||||
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
# SSL certificates (Let's Encrypt)
|
||||
# Run: certbot --nginx -d posterg.erg.be -d www.posterg.erg.be
|
||||
ssl_certificate /etc/letsencrypt/live/posterg.erg.be/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/posterg.erg.be/privkey.pem;
|
||||
|
||||
# SSL configuration
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
# Security headers (HTTPS)
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
|
||||
|
||||
# Disable server tokens
|
||||
server_tokens off;
|
||||
|
||||
# Max upload size
|
||||
client_max_body_size 100M;
|
||||
client_body_timeout 120s;
|
||||
|
||||
# Logging
|
||||
access_log /var/log/nginx/posterg_ssl_access.log;
|
||||
error_log /var/log/nginx/posterg_ssl_error.log warn;
|
||||
|
||||
# Block common attack patterns
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~ \.(git|env|db-journal)$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# Deny access to sensitive files
|
||||
location ~* \.(md|txt|sql|sh|json)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to database files
|
||||
location ~* \.db$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to shared/ directory
|
||||
location /shared/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to tests directory
|
||||
location /tests/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Deny access to cache directory
|
||||
location /cache/ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Admin panel - password protected
|
||||
location /formulaire/ {
|
||||
alias /var/www/html/formulaire/;
|
||||
|
||||
# HTTP Basic Authentication
|
||||
auth_basic "Admin Access - Post-ERG";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd-posterg;
|
||||
|
||||
# Rate limiting
|
||||
limit_req zone=admin burst=5 nodelay;
|
||||
|
||||
# PHP handling
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
}
|
||||
|
||||
# Security headers
|
||||
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||
}
|
||||
|
||||
# Search endpoint - rate limiting
|
||||
location /search.php {
|
||||
limit_req zone=search burst=10 nodelay;
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
}
|
||||
|
||||
# Public PHP files
|
||||
location ~ \.php$ {
|
||||
limit_req zone=general burst=20 nodelay;
|
||||
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
|
||||
|
||||
# Security parameters
|
||||
fastcgi_param PHP_VALUE "upload_max_filesize=50M \n post_max_size=100M";
|
||||
fastcgi_param PHP_ADMIN_VALUE "open_basedir=/var/www/html:/tmp";
|
||||
|
||||
# Timeouts
|
||||
fastcgi_read_timeout 120;
|
||||
fastcgi_send_timeout 120;
|
||||
}
|
||||
|
||||
# Static files caching
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|otf)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# Root location
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
# Deny access to script files in data directories
|
||||
location ~* /data/.*\.(php|sh|py)$ {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user