mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
Reintroduce TFE duration metadata: DB columns, form fields, controllers, views, and migration
Add 'unsafe-eval' to CSP script-src directives (htmx requires Function())
This commit is contained in:
@@ -8,7 +8,6 @@ This directory contains nginx configuration and documentation for the Post-ERG t
|
||||
- **`docs/`** - Documentation
|
||||
- `PRODUCTION_DEPLOYMENT.md` - Deployment guide
|
||||
- `QUICK_REFERENCE.md` - Command reference
|
||||
- `ADMIN_USERS.md` - User management
|
||||
- `SECURITY_HEADERS.md` - Security headers reference
|
||||
- `PHP_AUTH_LAYER.md` - Authentication layer documentation
|
||||
- `HTACCESS_TO_NGINX.md` - Apache to nginx migration notes
|
||||
@@ -33,19 +32,16 @@ The deployment script will:
|
||||
- ✅ Test and reload nginx
|
||||
- ✅ Verify PHP-FPM is running
|
||||
|
||||
### Manage admin users
|
||||
### Manage admin password
|
||||
|
||||
```bash
|
||||
just manage-admin-users
|
||||
ssh xamxam "sudo bash /tmp/manage-admin-users.sh"
|
||||
```
|
||||
The admin password is managed via the admin panel at `/admin/parametres` → Account tab.
|
||||
|
||||
## 🔒 Security Features
|
||||
|
||||
### Admin Panel Protection
|
||||
- **Password required** for `/admin/`
|
||||
- HTTP Basic Authentication
|
||||
- Rate limited: 10 requests/minute
|
||||
- **Password required** for `/admin/` (password-only, no username)
|
||||
- PHP session-based authentication (`AdminAuth`)
|
||||
- Rate limited: 300 req/min, burst=30
|
||||
|
||||
### File Access Protection
|
||||
- Database files (`.db`) - **BLOCKED**
|
||||
@@ -59,7 +55,7 @@ ssh xamxam "sudo bash /tmp/manage-admin-users.sh"
|
||||
### Rate Limiting
|
||||
- General requests: 30/minute
|
||||
- Search endpoint: 30/minute
|
||||
- Admin panel: 10/minute
|
||||
- Admin panel: 300 req/min (burst=30)
|
||||
|
||||
### Security Headers
|
||||
- ✅ X-Frame-Options (clickjacking protection)
|
||||
@@ -72,7 +68,6 @@ ssh xamxam "sudo bash /tmp/manage-admin-users.sh"
|
||||
|
||||
- **[docs/PRODUCTION_DEPLOYMENT.md](docs/PRODUCTION_DEPLOYMENT.md)** - Complete deployment guide
|
||||
- **[docs/QUICK_REFERENCE.md](docs/QUICK_REFERENCE.md)** - Command reference and troubleshooting
|
||||
- **[docs/ADMIN_USERS.md](docs/ADMIN_USERS.md)** - Admin user management
|
||||
- **[docs/SECURITY_HEADERS.md](docs/SECURITY_HEADERS.md)** - Security headers reference
|
||||
|
||||
## 🧪 Testing
|
||||
@@ -90,11 +85,6 @@ curl -I https://xamxam.erg.be/ | grep -E "X-|Strict-Transport"
|
||||
|
||||
## 🆘 Quick Help
|
||||
|
||||
### Admin can't log in
|
||||
```bash
|
||||
sudo htpasswd /etc/nginx/.htpasswd-xamxam admin
|
||||
```
|
||||
|
||||
### 502 Bad Gateway
|
||||
```bash
|
||||
sudo systemctl status php8.4-fpm
|
||||
|
||||
@@ -26,10 +26,7 @@ sudo bash /tmp/deploy-server.sh
|
||||
|
||||
### 3. Set admin password (first time only)
|
||||
|
||||
```bash
|
||||
just manage-admin-users
|
||||
ssh xamxam "sudo bash /tmp/manage-admin-users.sh"
|
||||
```
|
||||
Visit `/admin/parametres` → Account tab and set the admin password there.
|
||||
|
||||
## Manual Setup Steps
|
||||
|
||||
@@ -37,15 +34,16 @@ ssh xamxam "sudo bash /tmp/manage-admin-users.sh"
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install nginx apache2-utils php8.4-fpm
|
||||
sudo apt install nginx php8.4-fpm php8.4-curl php8.4-sqlite3
|
||||
```
|
||||
|
||||
### 2. Create Admin Password
|
||||
### 2. Set admin password
|
||||
|
||||
Visit `/admin/parametres` → Account tab in the admin panel to set the password.
|
||||
|
||||
Or generate a hash and insert it directly:
|
||||
```bash
|
||||
just manage-admin-users
|
||||
# Then on the server:
|
||||
ssh xamxam "sudo bash /tmp/manage-admin-users.sh"
|
||||
php -r "echo password_hash('your-secret-password', PASSWORD_BCRYPT);"
|
||||
```
|
||||
|
||||
### 3. Copy Nginx Configuration
|
||||
@@ -69,11 +67,8 @@ sudo systemctl status nginx
|
||||
### Test Admin Authentication
|
||||
|
||||
```bash
|
||||
# Should return 401
|
||||
# Should redirect to login page (302)
|
||||
curl -I https://xamxam.erg.be/admin/
|
||||
|
||||
# With credentials
|
||||
curl -u admin:password https://xamxam.erg.be/admin/
|
||||
```
|
||||
|
||||
### Test File Protection
|
||||
@@ -92,12 +87,6 @@ curl -I https://xamxam.erg.be/ | grep -E "X-|Strict-Transport"
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### 403 Forbidden on admin
|
||||
```bash
|
||||
sudo ls -l /etc/nginx/.htpasswd-xamxam
|
||||
sudo chmod 644 /etc/nginx/.htpasswd-xamxam
|
||||
```
|
||||
|
||||
### 502 Bad Gateway
|
||||
```bash
|
||||
sudo systemctl status php8.4-fpm
|
||||
@@ -112,8 +101,10 @@ sudo nginx -t
|
||||
## Maintenance
|
||||
|
||||
### Change Admin Password
|
||||
|
||||
Visit `/admin/parametres` → Account tab or generate a new hash:
|
||||
```bash
|
||||
sudo htpasswd /etc/nginx/.htpasswd-xamxam admin
|
||||
php -r "echo password_hash('new-password', PASSWORD_BCRYPT);"
|
||||
```
|
||||
|
||||
### Reload Configuration
|
||||
@@ -125,4 +116,4 @@ sudo nginx -t && sudo systemctl reload nginx
|
||||
|
||||
- **[docs/PRODUCTION_DEPLOYMENT.md](docs/PRODUCTION_DEPLOYMENT.md)** - Detailed deployment
|
||||
- **[docs/QUICK_REFERENCE.md](docs/QUICK_REFERENCE.md)** - Command reference
|
||||
- **[docs/ADMIN_USERS.md](docs/ADMIN_USERS.md)** - User management
|
||||
- **[docs/PHP_AUTH_LAYER.md](docs/PHP_AUTH_LAYER.md)** - Auth layer documentation
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
# Managing Admin Users - Post-ERG
|
||||
|
||||
Quick guide to manage admin users for the Post-ERG admin panel.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Quick Commands
|
||||
|
||||
### Interactive Menu (Recommended)
|
||||
|
||||
```bash
|
||||
# From your local machine
|
||||
just manage-admin-users
|
||||
|
||||
# Then on the server
|
||||
ssh xamxam
|
||||
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 xamxam
|
||||
sudo cut -d: -f1 /etc/nginx/.htpasswd-xamxam
|
||||
```
|
||||
|
||||
### Change Password for Existing User
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo htpasswd /etc/nginx/.htpasswd-xamxam username_here
|
||||
```
|
||||
|
||||
You'll be prompted to enter the new password twice.
|
||||
|
||||
### Add New User
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo htpasswd /etc/nginx/.htpasswd-xamxam new_username
|
||||
```
|
||||
|
||||
### Delete User
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo htpasswd -D /etc/nginx/.htpasswd-xamxam username_to_delete
|
||||
```
|
||||
|
||||
### Reset Everything (Start Fresh)
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd-xamxam 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 manage-admin-users
|
||||
|
||||
# Or manually:
|
||||
rsync -v scripts/manage-admin-users.sh xamxam:/tmp/manage-admin-users.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Current Setup
|
||||
|
||||
After deployment, your admin panel has:
|
||||
- **URL:** https://xamxam.erg.be/admin/
|
||||
- **Current user:** `test_posterg_22@`
|
||||
- **Password:** Set during initial deployment
|
||||
|
||||
---
|
||||
|
||||
## 💡 Common Scenarios
|
||||
|
||||
### Scenario 1: Change Current Password
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo htpasswd /etc/nginx/.htpasswd-xamxam test_posterg_22@
|
||||
# Enter new password when prompted
|
||||
```
|
||||
|
||||
### Scenario 2: Change Username
|
||||
|
||||
Since you can't rename users, you need to:
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
# Add new user
|
||||
sudo htpasswd /etc/nginx/.htpasswd-xamxam new_username
|
||||
# Delete old user
|
||||
sudo htpasswd -D /etc/nginx/.htpasswd-xamxam test_posterg_22@
|
||||
```
|
||||
|
||||
### Scenario 3: Forgot Username
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo cut -d: -f1 /etc/nginx/.htpasswd-xamxam
|
||||
```
|
||||
|
||||
### Scenario 4: Multiple Admins
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
# Add second admin
|
||||
sudo htpasswd /etc/nginx/.htpasswd-xamxam admin2
|
||||
# Add third admin
|
||||
sudo htpasswd /etc/nginx/.htpasswd-xamxam admin3
|
||||
```
|
||||
|
||||
All users can log into `/admin/` with their own credentials.
|
||||
|
||||
### Scenario 5: Start Over with New Username
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
# This will DELETE ALL existing users and create a new one
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd-xamxam new_admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
After changing users/passwords:
|
||||
|
||||
```bash
|
||||
# Test that password is required
|
||||
curl -I https://xamxam.erg.be/admin/
|
||||
# Should return: 401 Unauthorized
|
||||
|
||||
# Test with credentials
|
||||
curl -u username:password https://xamxam.erg.be/admin/
|
||||
# Should return: 200 OK
|
||||
```
|
||||
|
||||
No nginx reload needed - changes take effect immediately!
|
||||
|
||||
---
|
||||
|
||||
## 📊 Password File Details
|
||||
|
||||
**Location:** `/etc/nginx/.htpasswd-xamxam`
|
||||
|
||||
**Format:** Standard Apache htpasswd format
|
||||
```
|
||||
username:$apr1$encrypted_password_hash
|
||||
```
|
||||
|
||||
**Permissions:**
|
||||
```bash
|
||||
-rw-r--r-- root root /etc/nginx/.htpasswd-xamxam
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Security Tips
|
||||
|
||||
1. **Use Strong Passwords**
|
||||
```bash
|
||||
# Generate a strong password
|
||||
openssl rand -base64 32
|
||||
```
|
||||
|
||||
2. **Avoid Common Usernames**
|
||||
- ❌ Bad: `admin`, `administrator`, `root`
|
||||
- ✅ Good: `xamxam_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 xamxam
|
||||
sudo grep "admin" /var/log/nginx/xamxam_access.log
|
||||
```
|
||||
|
||||
5. **Backup Password File**
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo cp /etc/nginx/.htpasswd-xamxam /etc/nginx/.htpasswd-xamxam.backup
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Troubleshooting
|
||||
|
||||
### "401 Unauthorized" even with correct password
|
||||
|
||||
**Check file exists:**
|
||||
```bash
|
||||
ssh xamxam
|
||||
ls -la /etc/nginx/.htpasswd-xamxam
|
||||
```
|
||||
|
||||
**Verify user exists:**
|
||||
```bash
|
||||
sudo cat /etc/nginx/.htpasswd-xamxam
|
||||
```
|
||||
|
||||
**Check nginx config:**
|
||||
```bash
|
||||
sudo grep -A 5 "auth_basic" /etc/nginx/sites-available/xamxam
|
||||
```
|
||||
|
||||
### Can't change password - "command not found"
|
||||
|
||||
**Install apache2-utils:**
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo apt update
|
||||
sudo apt install apache2-utils
|
||||
```
|
||||
|
||||
### Password file got deleted
|
||||
|
||||
**Recreate it:**
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo htpasswd -c /etc/nginx/.htpasswd-xamxam new_admin
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 Quick Reference
|
||||
|
||||
| Task | Command |
|
||||
|------|---------|
|
||||
| **Interactive menu** | `sudo bash /tmp/manage-admin-users.sh` |
|
||||
| **List users** | `sudo cut -d: -f1 /etc/nginx/.htpasswd-xamxam` |
|
||||
| **Change password** | `sudo htpasswd /etc/nginx/.htpasswd-xamxam username` |
|
||||
| **Add user** | `sudo htpasswd /etc/nginx/.htpasswd-xamxam newuser` |
|
||||
| **Delete user** | `sudo htpasswd -D /etc/nginx/.htpasswd-xamxam username` |
|
||||
| **Reset all** | `sudo htpasswd -c /etc/nginx/.htpasswd-xamxam 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://xamxam.erg.be/admin/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Remember:** Store passwords securely using a password manager! 🔐
|
||||
@@ -6,53 +6,32 @@
|
||||
|
||||
## Overview
|
||||
|
||||
The admin panel uses **two independent authentication layers** with a single UX prompt:
|
||||
The admin panel uses a single **PHP session-based authentication** layer.
|
||||
Authentication is password-only (no username required).
|
||||
|
||||
| Layer | Mechanism | Configured by |
|
||||
|-------|-----------|---------------|
|
||||
| **1st** | nginx HTTP Basic Auth | `/etc/nginx/.htpasswd-xamxam` (see `ADMIN_USERS.md`) |
|
||||
| **2nd** | PHP session guard (`src/AdminAuth.php`) | `config/admin_credentials.php` |
|
||||
| **PHP** | Session guard (`src/AdminAuth.php`) | `site_settings.admin_password_hash` in DB |
|
||||
|
||||
The user only sees **one prompt** (the browser Basic Auth dialog). PHP reads the
|
||||
same password from `$_SERVER['PHP_AUTH_PW']` and validates it independently with
|
||||
`password_verify`. On success it creates a session so subsequent requests skip
|
||||
the `password_verify` call.
|
||||
|
||||
---
|
||||
|
||||
## Why two layers?
|
||||
|
||||
nginx Basic Auth alone is a **single point of failure**:
|
||||
|
||||
- Reverse-proxy misconfiguration could expose admin routes directly.
|
||||
- Local development without the proxy leaves admin unprotected.
|
||||
- A misconfigured `auth_basic off` block (e.g., in a nested location) could bypass it.
|
||||
|
||||
The PHP session guard (`AdminAuth::requireLogin()`) is ~100 lines of PHP stdlib
|
||||
(`password_verify` + `session_regenerate_id`) with negligible attack surface.
|
||||
The user sees an HTML login form at `/admin/login.php` that asks only for a
|
||||
password. On successful login, a PHP session is created and all admin pages
|
||||
use `AdminAuth::requireLogin()` to enforce the guard.
|
||||
|
||||
## Authentication flow
|
||||
|
||||
```
|
||||
Browser → nginx Basic Auth dialog (username + password)
|
||||
Browser → /admin/login.php (HTML password-only form)
|
||||
│
|
||||
▼
|
||||
nginx validates against .htpasswd ──✗──▶ 401
|
||||
│ ✓
|
||||
▼
|
||||
PHP: AdminAuth::requireLogin()
|
||||
├─ session already live? ──✓──▶ proceed
|
||||
├─ $_SERVER['PHP_AUTH_PW'] set?
|
||||
│ └─ password_verify(PHP_AUTH_PW, ADMIN_PASSWORD_HASH)
|
||||
│ ├─ ✓ → create session → proceed (normal path)
|
||||
│ └─ ✗ → redirect to login form
|
||||
└─ neither → redirect to login form (proxy bypass)
|
||||
POST password → AdminAuth::login()
|
||||
├─ password_verify(password, stored_hash)
|
||||
│ ├─ ✓ → create session → redirect to /admin/
|
||||
│ └─ ✗ → show error, stay on login form
|
||||
└─
|
||||
```
|
||||
|
||||
The login form (`/admin/login.php`) is a **fallback** for when the reverse proxy
|
||||
is absent. In normal production use the user never sees it.
|
||||
|
||||
---
|
||||
If no password hash is stored in the DB (dev / cli-server), `AdminAuth`
|
||||
is a no-op — all admin pages are open.
|
||||
|
||||
## PHP auth setup (production)
|
||||
|
||||
@@ -61,19 +40,13 @@ is absent. In normal production use the user never sees it.
|
||||
php -r "echo password_hash('your-secret-password', PASSWORD_DEFAULT);"
|
||||
```
|
||||
|
||||
2. Create `config/admin_credentials.php` (outside the webroot, never committed):
|
||||
```php
|
||||
<?php
|
||||
define('ADMIN_PASSWORD_HASH', '$2y$12$<paste-hash-here>');
|
||||
2. Store it in the DB via the admin panel at `/admin/parametres` (Account tab)
|
||||
or by inserting directly:
|
||||
```sql
|
||||
INSERT INTO site_settings (key, value) VALUES ('admin_password_hash', '$2y$12$...')
|
||||
ON CONFLICT(key) DO UPDATE SET value = excluded.value;
|
||||
```
|
||||
|
||||
3. The `bootstrap.php` auto-loads this file if it exists.
|
||||
|
||||
If `ADMIN_PASSWORD_HASH` is not defined (development / cli-server), the PHP
|
||||
auth layer is a **no-op** — nginx Basic Auth remains the sole guard.
|
||||
|
||||
---
|
||||
|
||||
## Session cookie hardening (TODO item #8)
|
||||
|
||||
`AdminAuth::startSession()` calls `session_set_cookie_params()` before
|
||||
@@ -87,28 +60,15 @@ auth layer is a **no-op** — nginx Basic Auth remains the sole guard.
|
||||
| `Path` | `/admin` |
|
||||
| `Lifetime` | `0` (session cookie, expires on browser close) |
|
||||
|
||||
This replaces all direct `session_start()` calls in admin PHP files.
|
||||
|
||||
---
|
||||
|
||||
## Logout
|
||||
|
||||
A **Déconnexion** button is shown in the admin nav when `ADMIN_PASSWORD_HASH`
|
||||
is defined. It hits `/admin/logout.php` which destroys the PHP session.
|
||||
nginx Basic Auth invalidation requires closing the browser tab / window.
|
||||
A **Déconnexion** button is shown in the admin nav when a password hash is
|
||||
configured. It hits `/admin/logout.php` which destroys the PHP session.
|
||||
|
||||
---
|
||||
## Files
|
||||
|
||||
## Files changed
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/AdminAuth.php` | New — auth guard class |
|
||||
| `config/admin_credentials.php` | New — credential store (gitignored) |
|
||||
| `config/admin_credentials.example.php` | New — example / template |
|
||||
| `config/bootstrap.php` | Load credentials on startup |
|
||||
| `public/admin/*.php` | Replace `session_start()` with `AdminAuth::requireLogin()` |
|
||||
| `public/admin/actions/*.php` | Same |
|
||||
| `public/admin/login.php` | New — login form |
|
||||
| `public/admin/logout.php` | New — logout handler |
|
||||
| `public/admin/inc/head.php` | Logout button in nav |
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `src/AdminAuth.php` | Auth guard class |
|
||||
| `public/admin/login.php` | Login form (password-only) |
|
||||
| `public/admin/logout.php` | Logout handler |
|
||||
|
||||
@@ -37,8 +37,8 @@ server {
|
||||
|
||||
# Security headers
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload;" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none';" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none';" always;
|
||||
add_header X-Frame-Options "DENY" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
|
||||
@@ -115,12 +115,8 @@ server {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Admin panel - password protected
|
||||
# Admin panel - password protected at the PHP layer (AdminAuth)
|
||||
location ^~ /admin/ {
|
||||
# HTTP Basic Authentication (first layer)
|
||||
auth_basic "Admin Access - XAMXAM";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd-xamxam;
|
||||
|
||||
# Rate limiting for admin
|
||||
# 300r/m rate + burst=30 allows all concurrent HTMX fragments (up to ~12
|
||||
# on contenus.php) while still capping brute-force at 5 req/s sustained.
|
||||
@@ -129,12 +125,13 @@ server {
|
||||
# Content-Security-Policy - Admin policy
|
||||
# script-src needs 'unsafe-inline' for the OverType editor init block
|
||||
# and the live-reload poller (dev only). Admin is already auth-gated.
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none';" always;
|
||||
# 'unsafe-eval' is required by htmx (uses Function() internally).
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; frame-ancestors 'none';" always;
|
||||
|
||||
# Disable directory listing
|
||||
autoindex off;
|
||||
|
||||
# PHP handling for admin (AdminAuth provides second layer)
|
||||
# PHP handling for admin (AdminAuth provides auth layer)
|
||||
location ~ \.php$ {
|
||||
include snippets/fastcgi-php.conf;
|
||||
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
|
||||
@@ -168,8 +165,24 @@ server {
|
||||
}
|
||||
|
||||
# /media — served by front controller (MediaController validates + streams)
|
||||
# Override frame-ancestors to 'self' so Firefox's built-in PDF viewer
|
||||
# can display PDFs inline (Firefox uses an internal iframe for PDF.js).
|
||||
# Direct fastcgi_pass to /index.php (no try_files) so add_header survives —
|
||||
# try_files triggers an internal redirect to location = /index.php, which
|
||||
# loses this CSP override and inherits the server-block frame-ancestors 'none'.
|
||||
location = /media {
|
||||
try_files $uri /index.php$is_args$args;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; frame-ancestors 'self';" always;
|
||||
# Direct fastcgi_pass to /index.php (no try_files) so add_header survives.
|
||||
# We can't use snippets/fastcgi-php.conf because its try_files
|
||||
# $fastcgi_script_name =404 would fail — $fastcgi_script_name is /media
|
||||
# (no .php extension). Include fastcgi.conf directly instead.
|
||||
include fastcgi.conf;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
|
||||
fastcgi_param SCRIPT_NAME /index.php;
|
||||
fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
|
||||
fastcgi_param PHP_VALUE "upload_max_filesize=8192M \n post_max_size=8192M";
|
||||
fastcgi_read_timeout 600;
|
||||
fastcgi_send_timeout 600;
|
||||
}
|
||||
|
||||
# /live-reload — served by front controller
|
||||
|
||||
@@ -113,12 +113,8 @@ server {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Admin panel - password protected
|
||||
# Admin panel - password protected at the PHP layer (AdminAuth)
|
||||
location ^~ /admin/ {
|
||||
# HTTP Basic Authentication (first layer)
|
||||
auth_basic "Admin Access - Post-ERG";
|
||||
auth_basic_user_file /etc/nginx/.htpasswd-xamxam;
|
||||
|
||||
# Rate limiting for admin
|
||||
limit_req zone=admin burst=5 nodelay;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user