Files
Myron Blair a0b8bf2a09 security: remove stray !install!! deploy folder, block .py files, move secrets out of webroot
- Delete !install!!/ (schema.sql, migrations, fix_tjj.py) - unreferenced leftover
  deploy artifacts, fix_tjj.py was publicly downloadable (200) since the folder
  name did not match the existing /install/ block pattern
- .htaccess: add .py to blocked extensions, explicitly block the !install!!/ path
- config/config.php: replace with a require shim pointing to config-secrets.php
  outside the web root (Stripe/CyberMail keys no longer sit in a web-servable file)
2026-07-05 05:18:50 +00:00

106 lines
3.6 KiB
ApacheConf

# Tom's Java Jive - Apache Configuration
# Enable URL rewriting
RewriteEngine On
# Block sensitive paths outright. RedirectMatch/FilesMatch/Require/Order
# directives were confirmed NOT to be honored on this LiteSpeed setup (config/,
# includes/*.php, and .git/ were all still reachable live despite the
# RedirectMatch rules further down) — only mod_rewrite matching on REQUEST_URI
# is confirmed to actually work here. This must come before other rewrites.
RewriteCond %{REQUEST_URI} ^/(\.git|config/|includes/.*\.php|install/|!install!!/|db/)
RewriteRule .* - [F,L]
RewriteCond %{REQUEST_URI} \.sql$ [OR]
RewriteCond %{REQUEST_URI} \.py$
RewriteRule .* - [F,L]
# Force HTTPS (uncomment in production)
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Remove trailing slashes
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Protect sensitive directories
RedirectMatch 403 /config/.*$
RedirectMatch 403 /includes/.*\.php$
RedirectMatch 403 /install/.*$
RedirectMatch 403 /db/.*$
# Block .git (full source + commit history, including any credentials ever
# committed to it) from ever being served. NOTE: on the live server this
# repo's .git directory lives inside the docroot itself (deployed via
# `git clone` directly into public_html) and was confirmed reachable over
# HTTP (.git/config, .git/logs/HEAD, etc. all returned real content) even
# though the RedirectMatch rules above were also confirmed NOT blocking
# /config/*.php or /includes/*.php live — meaning .htaccess directives are
# not being fully honored by the current web server. This needs a server
# config fix (vhost-level deny, or moving .git outside the docroot) in
# addition to this file — see review notes.
RedirectMatch 403 /\.git/.*$
RedirectMatch 403 /\.git$
<FilesMatch "\.sql$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
</FilesMatch>
# Set default charset
AddDefaultCharset UTF-8
# Disable directory listing
Options -Indexes
# Set timezone (optional)
# php_value date.timezone "America/New_York"
# Increase upload limits (adjust as needed)
php_value upload_max_filesize 10M
php_value post_max_size 10M
# Enable compression (optional)
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json
</IfModule>
# Browser caching (optional)
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
# Security headers
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
</IfModule>
# Custom error pages (optional)
# ErrorDocument 404 /404.php
# ErrorDocument 500 /500.php
# SEO ADDITIONS
RewriteCond %{HTTP_HOST} ^www\.tomsjavajive\.com [NC]
RewriteRule ^(.*)$ https://tomsjavajive.com/$1 [R=301,L]
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>