Files
xamxam/nginx/QUICK_REFERENCE.md
Théophile Gervreau-Mercier 467aced734 Restructure repository and implement secure search feature
Phase 1: Consolidate shared infrastructure
- Create shared/ directory for common code
- Consolidate Database.php from front-backend and formulaire into unified shared/Database.php
  - Smart path detection for test.db vs posterg.db
  - Secure search with wildcard escaping and input validation
  - Support both singleton and direct instantiation patterns
  - Full CRUD methods for admin functionality
- Move RateLimit.php to shared/ (30 requests/min)
- Update all require paths across apps to use shared/

Phase 2: Reorganize directory structure
- Rename front-backend/ → apps/public/
- Rename formulaire/ → apps/admin/
- Rename db/ → database/
- Update all file paths for new structure
- Create root .gitignore excluding databases, cache, logs

Implement secure search feature
- Add apps/public/search.php with full-text search across theses
- Search filters: query, year, orientation, AP program, keywords
- Security features:
  - SQL injection prevention (prepared statements)
  - Wildcard injection prevention (escape % and _)
  - Input validation (max 200 chars, year range 1900-2100)
  - Rate limiting (30 req/min per IP)
  - Pagination limited to 100 results/page
  - XSS protection (htmlspecialchars on output)

Add comprehensive test suite
- Create apps/public/tests/ with proper structure
  - tests/Integration/SearchTest.php - 12 search scenarios
  - tests/Security/SecurityTest.php - vulnerability testing
  - tests/Unit/RateLimitTest.php - rate limit behavior
- Create database/fixtures/CreateTestDatabase.php
- Add apps/public/run-tests.php test runner
- All tests passing (4/4 suites)

Update deployment configuration
- Rename justfile 'sync' recipe to 'deploy'
- Create deploy group with separate deploy-public and deploy-admin
- Add test-deploy recipe for test database
- Exclude *.db, tests/, cache/, *.md from production deploy
- Deploy shared/ to both public and admin locations

Stats: +4482 insertions, -654 deletions across 72 files
2026-02-02 18:53:58 +01:00

5.4 KiB

Nginx Quick Reference - Post-ERG

Setup Commands

# 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/

# Test configuration
sudo nginx -t

# Reload nginx
sudo systemctl reload nginx

Common Operations

Password Management

# Add new user
sudo htpasswd /etc/nginx/.htpasswd-posterg username

# Change password for existing user
sudo htpasswd /etc/nginx/.htpasswd-posterg username

# Remove user
sudo htpasswd -D /etc/nginx/.htpasswd-posterg username

# List all users
sudo cut -d: -f1 /etc/nginx/.htpasswd-posterg

Nginx Control

# Test configuration
sudo nginx -t

# Reload configuration (no downtime)
sudo systemctl reload nginx

# Restart nginx (brief downtime)
sudo systemctl restart nginx

# Stop nginx
sudo systemctl stop nginx

# Start nginx
sudo systemctl start nginx

# Check status
sudo systemctl status nginx

View Logs

# Public site access log
sudo tail -f /var/log/nginx/posterg_access.log

# Public site errors
sudo tail -f /var/log/nginx/posterg_error.log

# SSL access log
sudo tail -f /var/log/nginx/posterg_ssl_access.log

# Search for specific pattern
sudo grep "404" /var/log/nginx/posterg_access.log

# Count requests by IP
sudo awk '{print $1}' /var/log/nginx/posterg_access.log | sort | uniq -c | sort -nr | head

SSL/HTTPS

# Get SSL certificate (Let's Encrypt)
sudo certbot --nginx -d posterg.erg.be -d www.posterg.erg.be

# Renew certificates
sudo certbot renew

# Check certificate expiry
sudo certbot certificates

# Test auto-renewal
sudo certbot renew --dry-run

Testing

Test Admin Authentication

# Should require password (returns 401)
curl -I https://posterg.erg.be/formulaire/

# With authentication
curl -u admin:password https://posterg.erg.be/formulaire/

Test Rate Limiting

# Should show increasing 429 responses after limit
for i in {1..50}; do
    curl -s -o /dev/null -w "%{http_code}\n" https://posterg.erg.be/
done

Test File Protection

# Should return 403
curl -I https://posterg.erg.be/database/posterg.db
curl -I https://posterg.erg.be/shared/Database.php
curl -I https://posterg.erg.be/.env

Test Security Headers

# Check all security headers
curl -I https://posterg.erg.be/ 2>&1 | grep -E "X-|Strict-Transport|Referrer|Permissions"

Troubleshooting

Common Issues

403 Forbidden on admin

# Check htpasswd file exists
sudo ls -l /etc/nginx/.htpasswd-posterg

# Check permissions
sudo chmod 644 /etc/nginx/.htpasswd-posterg

502 Bad Gateway

# Check PHP-FPM status
sudo systemctl status php8.2-fpm

# Restart PHP-FPM
sudo systemctl restart php8.2-fpm

# Check PHP-FPM logs
sudo tail /var/log/php8.2-fpm.log

Configuration errors

# Test config and show errors
sudo nginx -t

# Check nginx error log
sudo tail -50 /var/log/nginx/error.log

Emergency Recovery

# Disable password protection temporarily
sudo nano /etc/nginx/sites-available/posterg
# Comment out these lines in /formulaire/ location:
# auth_basic "Admin Access - Post-ERG";
# auth_basic_user_file /etc/nginx/.htpasswd-posterg;

# Reload nginx
sudo nginx -t && sudo systemctl reload nginx

Performance Monitoring

# Check active connections
sudo ss -tulpn | grep nginx

# Monitor nginx processes
watch -n 1 'ps aux | grep nginx'

# Check request rate
sudo tail -f /var/log/nginx/posterg_access.log | pv -l -r > /dev/null

# Disk usage of logs
sudo du -sh /var/log/nginx/*

Maintenance

# Rotate logs manually
sudo nginx -s reopen

# Clear old logs (keep last 7 days)
sudo find /var/log/nginx -name "*.log" -mtime +7 -delete

# Backup configuration
sudo cp /etc/nginx/sites-available/posterg /etc/nginx/sites-available/posterg.backup.$(date +%Y%m%d)

# Backup password file
sudo cp /etc/nginx/.htpasswd-posterg /etc/nginx/.htpasswd-posterg.backup.$(date +%Y%m%d)

Security Checklist

  • Admin password set: sudo ls -l /etc/nginx/.htpasswd-posterg
  • SSL enabled: curl -I https://posterg.erg.be/
  • Database blocked: curl -I https://posterg.erg.be/database/posterg.db
  • Shared directory blocked: curl -I https://posterg.erg.be/shared/Database.php
  • Rate limiting working: Test with curl loop
  • Security headers present: curl -I https://posterg.erg.be/ | grep X-
  • Logs accessible: sudo tail /var/log/nginx/posterg_access.log

Configuration Paths

  • Nginx config: /etc/nginx/sites-available/posterg
  • Password file: /etc/nginx/.htpasswd-posterg
  • SSL certificates: /etc/letsencrypt/live/posterg.erg.be/
  • Access logs: /var/log/nginx/posterg_access.log
  • Error logs: /var/log/nginx/posterg_error.log
  • PHP-FPM config: /etc/php/8.2/fpm/pool.d/www.conf
  • PHP-FPM socket: /var/run/php/php8.2-fpm.sock

Rate Limits (Current Settings)

  • General requests: 30 requests/minute
  • Search endpoint: 30 requests/minute (burst: 10)
  • Admin panel: 10 requests/minute (burst: 5)

To adjust, edit these lines in nginx config:

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;