Files
xamxam/nginx/SETUP.md
Théophile Gervreau-Mercier 7fca85d1c1 refactor: rename database → storage
More semantically accurate: contains SQLite files, schema, fixtures, test data.
Updated all references in code, scripts, docs.
2026-02-12 12:12:58 +01:00

370 lines
8.1 KiB
Markdown

# Nginx Setup for Post-ERG
This document explains how to set up nginx with security features and password protection for the admin panel.
## Prerequisites
- Ubuntu/Debian server with root access
- Nginx installed
- PHP-FPM installed (PHP 8.2 or later)
- Domain name pointed to your server
## Installation 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
```
### 2. Create Password File for Admin Panel
Create a password-protected admin area:
```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
```
### 4. Update Domain Name
Edit the configuration to use your domain:
```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
```bash
# Should prompt for password
curl -I https://posterg.erg.be/formulaire/
# With credentials
curl -u admin:your_password https://posterg.erg.be/formulaire/
```
### Test Rate Limiting
```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
```
### 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
```
## 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
### "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`
### "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
## 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
```bash
# Manual renewal
sudo certbot renew
# Check expiry
sudo certbot certificates
```
### Update Configuration
```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.