simplify web server configs (#65)
Reviewed-on: https://gitea.subcultureofone.org/greg/tkr/pulls/65 Co-authored-by: Greg Sarjeant <greg@subcultureofone.org> Co-committed-by: Greg Sarjeant <greg@subcultureofone.org>
This commit is contained in:
		
							parent
							
								
									195de75b78
								
							
						
					
					
						commit
						86abf587f6
					
				| @ -7,13 +7,17 @@ declare(strict_types=1); | ||||
| 
 | ||||
| // Define all the important paths
 | ||||
| define('APP_ROOT', dirname(dirname(__FILE__))); | ||||
| // Root-level directories
 | ||||
| define('CONFIG_DIR', APP_ROOT . '/config'); | ||||
| define('PUBLIC_DIR', APP_ROOT . '/public'); | ||||
| define('SRC_DIR', APP_ROOT . '/src'); | ||||
| define('STORAGE_DIR', APP_ROOT . '/storage'); | ||||
| define('TEMPLATES_DIR', APP_ROOT . '/templates'); | ||||
| define('DATA_DIR', STORAGE_DIR . '/db'); | ||||
| define('DB_FILE', DATA_DIR . '/tkr.sqlite'); | ||||
| // Storage subdirectories
 | ||||
| define('CSS_UPLOAD_DIR', STORAGE_DIR . '/upload/css'); | ||||
| define('DATA_DIR', STORAGE_DIR . '/db'); | ||||
| define('TEMPLATES_DIR', APP_ROOT . '/templates'); | ||||
| // Database file
 | ||||
| define('DB_FILE', DATA_DIR . '/tkr.sqlite'); | ||||
| 
 | ||||
| // Janky autoloader function
 | ||||
| // This is a bit more consistent with current frameworks
 | ||||
|  | ||||
| @ -1,49 +1,19 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdirectory path | ||||
| # on shared hosting via .htaccess | ||||
| # | ||||
| # e.g. http://www.my-domain.com/tkr | ||||
| # | ||||
| # This should work without modification if you extract the app | ||||
| # to /tkr from your web document root | ||||
| # Basic .htaccess for tkr on shared hosting | ||||
| # For use with included docker-compose.yml | ||||
| 
 | ||||
| # Enable mod_rewrite | ||||
| RewriteEngine On | ||||
| 
 | ||||
| # Security headers | ||||
| Header always set X-Frame-Options "SAMEORIGIN" | ||||
| Header always set X-XSS-Protection "1; mode=block" | ||||
| Header always set X-Content-Type-Options "nosniff" | ||||
| 
 | ||||
| # Directory index | ||||
| # Set directory index | ||||
| DirectoryIndex public/index.php | ||||
| 
 | ||||
| # Security: Block direct access to .php files (except through rewrites) | ||||
| RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
| RewriteRule ^.*$ - [R=404,L] | ||||
| # Block access to sensitive directories | ||||
| RewriteRule ^(storage|src|templates|config)(/.*)?$ - [F,L] | ||||
| 
 | ||||
| # Security: Block access to sensitive directories | ||||
| RewriteRule ^(storage|src|templates|examples|config)(/.*)?$ - [F,L] | ||||
| 
 | ||||
| # Security: Block access to hidden files | ||||
| # Block access to hidden files | ||||
| RewriteRule ^\..*$ - [F,L] | ||||
| 
 | ||||
| # Cache CSS files for 1 hour | ||||
| <FilesMatch "\.css$"> | ||||
|     Header set Cache-Control "public, max-age=3600" | ||||
| </FilesMatch> | ||||
| 
 | ||||
| # Serve the one static file that exists: css/tkr.css | ||||
| # (Pass requests to css/custom/ through to the PHP app) | ||||
| RewriteCond %{REQUEST_URI} !^/css/custom/ | ||||
| RewriteRule ^css/tkr\.css$ public/css/tkr.css [L] | ||||
| 
 | ||||
| # 404 all other static files (images, js, fonts, etc.) | ||||
| # so those requests don't hit the PHP app | ||||
| # (this is to reduce load on the PHP app from bots and scanners) | ||||
| RewriteRule \.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$ - [R=404,L] | ||||
| 
 | ||||
| # Everything else goes to the front controller | ||||
| # Route everything else through public/index.php | ||||
| RewriteCond %{REQUEST_FILENAME} !-f | ||||
| RewriteCond %{REQUEST_FILENAME} !-d | ||||
| RewriteRule ^(.*)$ public/index.php [L] | ||||
|  | ||||
| @ -1,19 +1,21 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdomain root without SSL | ||||
| # e.g. http://tkr.my-domain.com/ | ||||
| # | ||||
| # NOTE: Do not use in production. | ||||
| #       This is provided for docker compose | ||||
| #       (The included docker-compose file will mount it in the container image) | ||||
| # Basic Apache VirtualHost for tkr | ||||
| # For use with included docker-compose.yml | ||||
| 
 | ||||
| # HTTP - redirect to HTTPS | ||||
| <VirtualHost *:80> | ||||
|     ServerName localhost | ||||
|     DocumentRoot /var/www/tkr/public | ||||
| 
 | ||||
|     # Security headers | ||||
|     Header always set X-Frame-Options "SAMEORIGIN" | ||||
|     Header always set X-XSS-Protection "1; mode=block" | ||||
|     Header always set X-Content-Type-Options "nosniff" | ||||
|     Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" | ||||
|     # Main directory - route everything through index.php | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
| 
 | ||||
|         RewriteEngine On | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ index.php [L] | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Block access to sensitive directories | ||||
|     <Directory "/var/www/tkr/storage"> | ||||
| @ -22,59 +24,13 @@ | ||||
|     <Directory "/var/www/tkr/src"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/config"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Block access to hidden files | ||||
|     <DirectoryMatch "^\.|/\."> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|     </DirectoryMatch> | ||||
| 
 | ||||
|     # Cache CSS files | ||||
|     <LocationMatch "\.css$"> | ||||
|         Header set Cache-Control "public, max-age=3600" | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # Serve static CSS file | ||||
|     Alias /css/tkr.css /var/www/tkr/public/css/tkr.css | ||||
| 
 | ||||
|     # 404 all non-css static files (images, js, fonts, etc.) | ||||
|     # so those requests don't hit the PHP app | ||||
|     # (this is to reduce load on the PHP app from bots and scanners) | ||||
|     <LocationMatch "\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$"> | ||||
|         <RequireAll> | ||||
|             Require all denied | ||||
|         </RequireAll> | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # Enable rewrite engine | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         Options -Indexes | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
| 
 | ||||
|         RewriteEngine On | ||||
| 
 | ||||
|         # Block direct PHP access | ||||
|         RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
|         RewriteRule ^.*$ - [R=404,L] | ||||
| 
 | ||||
|         # Serve the one static file that exists: css/tkr.css | ||||
|         # (Pass requests to css/custom/ through to the PHP app) | ||||
|         RewriteCond %{REQUEST_URI} !^/css/custom/ | ||||
|         RewriteRule ^css/tkr\.css$ css/tkr.css [L] | ||||
| 
 | ||||
|         # Everything else to front controller | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ index.php [L] | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Error and access logs | ||||
|     ErrorLog ${APACHE_LOG_DIR}/tkr_error.log | ||||
|     CustomLog ${APACHE_LOG_DIR}/tkr_access.log combined | ||||
| </VirtualHost> | ||||
|  | ||||
| @ -1,72 +1,38 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdirectory path without SSL | ||||
| # e.g. http://www.my-domain.com/tkr | ||||
| # | ||||
| # NOTE: Do not use in production. | ||||
| #       This is provided for docker compose | ||||
| #       (The included docker-compose file will mount it in the container image) | ||||
| # Basic Apache config for tkr in subfolder | ||||
| # e.g. https://your-domain.com/tkr | ||||
| # For use with included docker-compose.yml | ||||
| 
 | ||||
| # Alias for tkr subfolder | ||||
| <VirtualHost *:80> | ||||
|     ServerName localhost | ||||
|     DocumentRoot /var/www/html | ||||
| 
 | ||||
|     # Security headers | ||||
|     Header always set X-Frame-Options "SAMEORIGIN" | ||||
|     Header always set X-XSS-Protection "1; mode=block" | ||||
|     Header always set X-Content-Type-Options "nosniff" | ||||
|     Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" | ||||
| 
 | ||||
|     # tkr Application at /tkr | ||||
|     # NOTE: If you change the directory name, | ||||
|     # remember to update all instances of /var/www/tkr in this file to match | ||||
|     Alias /tkr /var/www/tkr/public | ||||
| 
 | ||||
|     # Block access to sensitive TKR directories | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
| 
 | ||||
|         # Front controller pattern | ||||
|         RewriteEngine On | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ /tkr/index.php [L] | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Block access to sensitive directories | ||||
|     <Directory "/var/www/tkr/storage"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/src"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/config"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
| 
 | ||||
|     # 404 all non-css static files in /tkr (images, js, fonts, etc.) | ||||
|     # so those requests don't hit the PHP app | ||||
|     # (this is to reduce load on the PHP app from bots and scanners) | ||||
|     <LocationMatch "^/tkr/.*\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$"> | ||||
|         <RequireAll> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|         </RequireAll> | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # tkr application directory | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         Options -Indexes | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
| 
 | ||||
|         RewriteEngine On | ||||
| 
 | ||||
|         # Block direct PHP access | ||||
|         RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
|         RewriteRule ^.*$ - [R=404,L] | ||||
| 
 | ||||
|         # Serve the one static file that exists: css/tkr.css | ||||
|         # (Pass requests to css/custom/ through to the PHP app) | ||||
|         RewriteCond %{REQUEST_URI} !^/tkr/css/custom/ | ||||
|         RewriteRule ^css/tkr\.css$ css/tkr.css [L] | ||||
| 
 | ||||
|         # Send everything else to the front controller | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ index.php [L] | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Error and access logs | ||||
|     ErrorLog ${APACHE_LOG_DIR}/my-domain_error.log | ||||
|     CustomLog ${APACHE_LOG_DIR}/my-domain_access.log combined | ||||
|     ErrorLog ${APACHE_LOG_DIR}/tkr_error.log | ||||
|     CustomLog ${APACHE_LOG_DIR}/tkr_access.log combined | ||||
| </VirtualHost> | ||||
| @ -1,100 +1,45 @@ | ||||
| # Example nginx config | ||||
| # for serving tkr as a subdomain without SSL | ||||
| # e.g. http://tkr.my-domain.com/ | ||||
| # | ||||
| # NOTE: Do not use in production. | ||||
| #       This is provided for docker compose | ||||
| #       (The included docker-compose file will mount it in the container image) | ||||
| # Basic nginx config for tkr | ||||
| # Replace "your-domain.com" with your actual domain | ||||
| # Replace "/var/www/tkr" with your installation path | ||||
| 
 | ||||
| # HTTP - redirect to HTTPS | ||||
| server { | ||||
|     listen 80; | ||||
|     listen 80 default_server; | ||||
|     server_name localhost; | ||||
| 
 | ||||
|     root /var/www/tkr/public; | ||||
|     index index.php; | ||||
| 
 | ||||
|     # Security headers | ||||
|     # The first rule is to prevent including in a frame on a different domain. | ||||
|     # Remove it if you want to do that. | ||||
|     add_header X-Frame-Options "SAMEORIGIN" always; | ||||
|     add_header X-XSS-Protection "1; mode=block" always; | ||||
|     add_header X-Content-Type-Options "nosniff" always; | ||||
|     # Block access to sensitive directories | ||||
|     location ~ ^/(storage|src|templates|config) { | ||||
|         deny all; | ||||
|         return 404; | ||||
|     } | ||||
| 
 | ||||
|     # Deny access to hidden files | ||||
|     # Block access to hidden files | ||||
|     location ~ /\. { | ||||
|         deny all; | ||||
|         access_log off; | ||||
|         log_not_found off; | ||||
|     } | ||||
| 
 | ||||
|     # PHP routing - everything goes through index.php | ||||
|     # Handle PHP files | ||||
|     location ~ \.php$ { | ||||
|         fastcgi_pass php:9000; | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
|     } | ||||
| 
 | ||||
|     # Front controller pattern - route everything else through index.php | ||||
|     location / { | ||||
|         # Cache static files | ||||
|         # Note that I don't actually serve most of this (just css) | ||||
|         # but this prevents requests for static content from getting to the PHP handler. | ||||
|         # | ||||
|         # I've excluded /css/custom so that requests for uploaded css can be handled by the PHP app. | ||||
|         # That lets me store uploaded content outside of the document root, | ||||
|         # so it isn't served directly. | ||||
| 
 | ||||
|         # CSS files - 1 hour cache | ||||
|         location ~* ^/(?!css/custom/).+\.css$ { | ||||
|             expires 1h; | ||||
|             add_header Cache-Control "public"; | ||||
|             try_files $uri =404; | ||||
|         try_files $uri $uri/ @tkr; | ||||
|     } | ||||
| 
 | ||||
|         # Other static assets - 1 year cache | ||||
|         location ~* ^/.+\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|             expires 1y; | ||||
|             add_header Cache-Control "public, immutable"; | ||||
|             try_files $uri =404; | ||||
|         } | ||||
| 
 | ||||
|         # index.php is the entry point | ||||
|         # It needs to be sent to php-fpm | ||||
|         # But if someone tries to directly access index.php, that file will throw a 404 | ||||
|         # so bots and scanners can't tell this is a php app | ||||
|         location = /index.php { | ||||
|             # If you're running php-fpm on the same server as nginx, | ||||
|             # then change this to the local php-fpm socket | ||||
|             # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|     # Handle PHP requests | ||||
|     location @tkr { | ||||
|         fastcgi_pass php:9000; | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|         # Block attempts to access all other .php files directly | ||||
|         # (these are bots and scanners) | ||||
|         location ~ ^/.+\.php$ { | ||||
|             return 404; | ||||
|         } | ||||
| 
 | ||||
|         # forward other requests to the fallback block, | ||||
|         # which sends them to php-fpm for handling | ||||
|         try_files $uri $uri/ @tkr_fallback; | ||||
|     } | ||||
| 
 | ||||
|     # Fallback for /tkr routing - all non-file requests (e.g. /login) go to index.php | ||||
|     location @tkr_fallback { | ||||
|         # If you're running php-fpm on the same server as nginx, | ||||
|         # then change this to the local php-fpm socket | ||||
|         # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|         fastcgi_pass php:9000; | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|     # Deny access to sensitive directories | ||||
|     location ~ ^/(storage|src|templates|uploads|config) { | ||||
|         deny all; | ||||
|         return 404; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,101 +1,47 @@ | ||||
| # Example nginx config | ||||
| # for serving tkr as a subdfolder without SSL | ||||
| # e.g. http://my-domain.com/tkr | ||||
| # | ||||
| # NOTE: Do not use in production. | ||||
| #       This is provided for docker compose | ||||
| #       (The included docker-compose file will mount it in the container image) | ||||
| # Basic nginx config for tkr in subfolder | ||||
| # e.g. https://your-domain.com/tkr | ||||
| # For use with included docker-compose.yml | ||||
| 
 | ||||
| server { | ||||
|     listen 80 default_server; | ||||
|     listen [::]:80 default_server; | ||||
| 
 | ||||
|     # replace localhost with your subdomain | ||||
|     # e.g. tkr.my-domain.com | ||||
|     server_name localhost; | ||||
| 
 | ||||
|     root /var/www/html; | ||||
|     index index.html; | ||||
| 
 | ||||
|     # Security headers | ||||
|     # The first rule is to prevent including in a frame on a different domain. | ||||
|     # Remove it if you want to do that. | ||||
|     add_header X-Frame-Options "SAMEORIGIN" always; | ||||
|     add_header X-XSS-Protection "1; mode=block" always; | ||||
|     add_header X-Content-Type-Options "nosniff" always; | ||||
| 
 | ||||
|     # Deny access to hidden files | ||||
|     location ~ /\. { | ||||
|         deny all; | ||||
|         access_log off; | ||||
|         log_not_found off; | ||||
|     } | ||||
| 
 | ||||
|     # PHP routing - everything under /tkr goes through index.php | ||||
|     location /tkr { | ||||
|         alias /var/www/tkr/public; | ||||
|         index index.php; | ||||
| 
 | ||||
|         # Cache static files | ||||
|         # Note that I don't actually serve most of this (just css) | ||||
|         # but this prevents requests for static content from getting to the PHP handler. | ||||
|         # | ||||
|         # I've excluded /css/custom so that requests for uploaded css can be handled by the PHP app. | ||||
|         # That lets me store uploaded content outside of the document root, | ||||
|         # so it isn't served directly. | ||||
| 
 | ||||
|         # CSS files - 1 hour cache | ||||
|         location ~* ^/tkr/(?!css/custom/).+\.css$ { | ||||
|             expires 1h; | ||||
|             add_header Cache-Control "public"; | ||||
|             try_files $uri =404; | ||||
|         } | ||||
| 
 | ||||
|         # Other static assets - 1 year cache | ||||
|         location ~* ^/tkr/.+\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|             expires 1y; | ||||
|             add_header Cache-Control "public, immutable"; | ||||
|             try_files $uri =404; | ||||
|         } | ||||
| 
 | ||||
|         # index.php is the entry point | ||||
|         # It needs to be sent to php-fpm | ||||
|         # But if someone tries to directly access index.php, that file will throw a 404 | ||||
|         # so bots and scanners can't tell this is a php app | ||||
|         location = /tkr/index.php { | ||||
|             fastcgi_pass php:9000; | ||||
|             fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|             include fastcgi_params; | ||||
| 
 | ||||
|             fastcgi_param REQUEST_METHOD $request_method; | ||||
|             fastcgi_param REQUEST_URI $request_uri; | ||||
|             fastcgi_param QUERY_STRING $query_string; | ||||
|         } | ||||
| 
 | ||||
|         # Block attempts to access all other .php files directly | ||||
|         # (these are bots and scanners) | ||||
|         location ~ ^/tkr/.+\.php$ { | ||||
|             return 404; | ||||
|         } | ||||
| 
 | ||||
|         # forward other requests to the fallback block, | ||||
|         # which sends them to php-fpm for handling | ||||
|         try_files $uri $uri/ @tkr_fallback; | ||||
|     } | ||||
| 
 | ||||
|     # Fallback for /tkr routing - all non-file requests (e.g. /login) go to index.php | ||||
|     location @tkr_fallback { | ||||
|         fastcgi_pass php:9000; | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|     # Deny access to sensitive directories | ||||
|     location ~ ^/tkr/(storage|src|templates|uploads|config) { | ||||
|         # Block access to sensitive directories | ||||
|         location ~ ^/tkr/(storage|src|templates|config) { | ||||
|             deny all; | ||||
|             return 404; | ||||
|         } | ||||
| 
 | ||||
|         # Block access to hidden files | ||||
|         location ~ /\. { | ||||
|             deny all; | ||||
|         } | ||||
| 
 | ||||
|         # Handle PHP files | ||||
|         location ~ \.php$ { | ||||
|             fastcgi_pass php:9000; | ||||
|             fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|             include fastcgi_params; | ||||
|         } | ||||
| 
 | ||||
|         # Front controller pattern | ||||
|         # Send everything else to index.php | ||||
|         try_files $uri $uri/ @tkr; | ||||
|     } | ||||
| 
 | ||||
|     location @tkr { | ||||
|         fastcgi_pass php:9000; | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| } | ||||
| @ -1,49 +1,20 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdirectory path | ||||
| # on shared hosting via .htaccess | ||||
| # | ||||
| # e.g. http://www.my-domain.com/tkr | ||||
| # | ||||
| # This should work without modification if you extract the app | ||||
| # to /tkr from your web document root | ||||
| # Basic .htaccess for tkr on shared hosting | ||||
| # Place this file inside the tkr directory | ||||
| # e.g. if tkr is at /public_html/tkr/, this goes in /public_html/tkr/ | ||||
| 
 | ||||
| # Enable mod_rewrite | ||||
| RewriteEngine On | ||||
| 
 | ||||
| # Security headers | ||||
| Header always set X-Frame-Options "SAMEORIGIN" | ||||
| Header always set X-XSS-Protection "1; mode=block" | ||||
| Header always set X-Content-Type-Options "nosniff" | ||||
| 
 | ||||
| # Directory index | ||||
| # Set directory index | ||||
| DirectoryIndex public/index.php | ||||
| 
 | ||||
| # Security: Block direct access to .php files (except through rewrites) | ||||
| RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
| RewriteRule ^.*$ - [R=404,L] | ||||
| # Block access to sensitive directories | ||||
| RewriteRule ^(storage|src|templates|config)(/.*)?$ - [F,L] | ||||
| 
 | ||||
| # Security: Block access to sensitive directories | ||||
| RewriteRule ^(storage|src|templates|examples|config)(/.*)?$ - [F,L] | ||||
| 
 | ||||
| # Security: Block access to hidden files | ||||
| # Block access to hidden files | ||||
| RewriteRule ^\..*$ - [F,L] | ||||
| 
 | ||||
| # Cache CSS files for 1 hour | ||||
| <FilesMatch "\.css$"> | ||||
|     Header set Cache-Control "public, max-age=3600" | ||||
| </FilesMatch> | ||||
| 
 | ||||
| # Serve the one static file that exists: css/tkr.css | ||||
| # (Pass requests to css/custom/ through to the PHP app) | ||||
| RewriteCond %{REQUEST_URI} !^/css/custom/ | ||||
| RewriteRule ^css/tkr\.css$ public/css/tkr.css [L] | ||||
| 
 | ||||
| # 404 all other static files (images, js, fonts, etc.) | ||||
| # so those requests don't hit the PHP app | ||||
| # (this is to reduce load on the PHP app from bots and scanners) | ||||
| RewriteRule \.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$ - [R=404,L] | ||||
| 
 | ||||
| # Everything else goes to the front controller | ||||
| # Route everything else through the front controller | ||||
| RewriteCond %{REQUEST_FILENAME} !-f | ||||
| RewriteCond %{REQUEST_FILENAME} !-d | ||||
| RewriteRule ^(.*)$ public/index.php [L] | ||||
|  | ||||
| @ -1,38 +1,33 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdomain root with SSL | ||||
| # e.g. https://tkr.my-domain.com/ | ||||
| # | ||||
| # Use SSL in production. | ||||
| # This is a minimal SSL confiuration | ||||
| # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ | ||||
| # Basic Apache VirtualHost for tkr | ||||
| # Replace "your-domain.com" with your actual domain | ||||
| # Replace "/var/www/tkr" with your installation path | ||||
| 
 | ||||
| # HTTP - redirect to HTTPS | ||||
| <VirtualHost *:80> | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName localhost | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     DocumentRoot /var/www/tkr/public | ||||
|     # Redirect HTTP to HTTPS | ||||
|     Redirect permanent / https://tkr.my-domain.com/ | ||||
|     ServerName your-domain.com | ||||
|     Redirect permanent / https://your-domain.com/ | ||||
| </VirtualHost> | ||||
| 
 | ||||
| # HTTPS | ||||
| <VirtualHost *:443> | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName localhost | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName your-domain.com | ||||
|     DocumentRoot /var/www/tkr/public | ||||
|      | ||||
|     # SSL Configuration | ||||
|     # SSL Configuration (using Let's Encrypt) | ||||
|     SSLEngine on | ||||
|     SSLCertificateFile /etc/letsencrypt/live/your-domain.com/fullchain.pem | ||||
|     SSLCertificateKeyFile /etc/letsencrypt/live/your-domain.com/privkey.pem | ||||
|      | ||||
|     # Assumes you're using letsencrypt for cert generation | ||||
|     # Replace with the actual paths to your cert and key | ||||
|     SSLCertificateFile /etc/letsencrypt/live/tkr.my-domain.com/fullchain.pem | ||||
|     SSLCertificateKeyFile /etc/letsencrypt/live/tkr.my-domain.com/privkey.pem | ||||
|     # Main directory - route everything through index.php | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
|          | ||||
|     # Security headers | ||||
|     Header always set X-Frame-Options "SAMEORIGIN" | ||||
|     Header always set X-XSS-Protection "1; mode=block" | ||||
|     Header always set X-Content-Type-Options "nosniff" | ||||
|     Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" | ||||
|         RewriteEngine On | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ index.php [L] | ||||
|     </Directory> | ||||
|      | ||||
|     # Block access to sensitive directories | ||||
|     <Directory "/var/www/tkr/storage"> | ||||
| @ -41,59 +36,13 @@ | ||||
|     <Directory "/var/www/tkr/src"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/config"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Block access to hidden files | ||||
|     <DirectoryMatch "^\.|/\."> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|     </DirectoryMatch> | ||||
| 
 | ||||
|     # Cache CSS files | ||||
|     <LocationMatch "\.css$"> | ||||
|         Header set Cache-Control "public, max-age=3600" | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # Serve static CSS file | ||||
|     Alias /css/tkr.css /var/www/tkr/public/css/tkr.css | ||||
| 
 | ||||
|     # 404 all non-css static files (images, js, fonts, etc.) | ||||
|     # so those requests don't hit the PHP app | ||||
|     # (this is to reduce load on the PHP app from bots and scanners) | ||||
|     <LocationMatch "\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$"> | ||||
|         <RequireAll> | ||||
|             Require all denied | ||||
|         </RequireAll> | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # Enable rewrite engine | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         Options -Indexes | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
| 
 | ||||
|         RewriteEngine On | ||||
| 
 | ||||
|         # Block direct PHP access | ||||
|         RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
|         RewriteRule ^.*$ - [R=404,L] | ||||
| 
 | ||||
|         # Serve the one static file that exists: css/tkr.css | ||||
|         # (Pass requests to css/custom/ through to the PHP app) | ||||
|         RewriteCond %{REQUEST_URI} !^/css/custom/ | ||||
|         RewriteRule ^css/tkr\.css$ css/tkr.css [L] | ||||
| 
 | ||||
|         # Everything else to front controller | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ index.php [L] | ||||
|     </Directory> | ||||
|      | ||||
|     # Error and access logs | ||||
|     ErrorLog ${APACHE_LOG_DIR}/tkr_error.log | ||||
|     CustomLog ${APACHE_LOG_DIR}/tkr_access.log combined | ||||
| </VirtualHost> | ||||
|  | ||||
| @ -1,91 +1,31 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdirectory path with SSL | ||||
| # e.g. https://www.my-domain.com/tkr | ||||
| # | ||||
| # Use SSL in production. | ||||
| # This is a minimal SSL confiuration | ||||
| # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ | ||||
| <VirtualHost *:80> | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName localhost | ||||
|     # CONFIG: Replace  with your subdomain, e.g. tkr.my-domain.com | ||||
|     DocumentRoot /var/www/tkr | ||||
|     # Redirect HTTP to HTTPS | ||||
|     Redirect permanent / https://my-domain.com/ | ||||
| </VirtualHost> | ||||
| # Basic Apache config for tkr in subfolder | ||||
| # e.g. https://your-domain.com/tkr | ||||
| # Add this to your existing VirtualHost configuration | ||||
| 
 | ||||
| <VirtualHost *:443> | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName localhost | ||||
|     # CONFIG: Replace  with your subdomain, e.g. tkr.my-domain.com | ||||
|     DocumentRoot /var/www/tkr/ | ||||
| 
 | ||||
|     # SSL Configuration | ||||
|     SSLEngine on | ||||
| 
 | ||||
|     # Assumes you're using letsencrypt for cert generation | ||||
|     # Replace with the actual paths to your cert and key | ||||
|     SSLCertificateFile /etc/letsencrypt/live/my-domain.com/fullchain.pem | ||||
|     SSLCertificateKeyFile /etc/letsencrypt/live/my-domain.com/privkey.pem | ||||
| 
 | ||||
|     # Security headers | ||||
|     Header always set X-Frame-Options "SAMEORIGIN" | ||||
|     Header always set X-XSS-Protection "1; mode=block" | ||||
|     Header always set X-Content-Type-Options "nosniff" | ||||
|     Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" | ||||
| 
 | ||||
|     # tkr Application at /tkr | ||||
|     # NOTE: If you change the directory name, | ||||
|     # remember to update all instances of /var/www/tkr in this file to match | ||||
| # Alias for tkr subfolder | ||||
| Alias /tkr /var/www/tkr/public | ||||
| 
 | ||||
|     # Block access to sensitive TKR directories | ||||
| <Directory "/var/www/tkr/public"> | ||||
|     AllowOverride None | ||||
|     Require all granted | ||||
|      | ||||
|     # Front controller pattern | ||||
|     RewriteEngine On | ||||
|     RewriteCond %{REQUEST_FILENAME} !-f | ||||
|     RewriteCond %{REQUEST_FILENAME} !-d | ||||
|     RewriteRule ^(.*)$ /tkr/index.php [L] | ||||
| </Directory> | ||||
| 
 | ||||
| # Block access to sensitive directories | ||||
| <Directory "/var/www/tkr/storage"> | ||||
|     Require all denied | ||||
| </Directory> | ||||
| <Directory "/var/www/tkr/src"> | ||||
|     Require all denied | ||||
| </Directory> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
| <Directory "/var/www/tkr/config"> | ||||
|     Require all denied | ||||
| </Directory> | ||||
| 
 | ||||
|     # 404 all non-css static files in /tkr (images, js, fonts, etc.) | ||||
|     # so those requests don't hit the PHP app | ||||
|     # (this is to reduce load on the PHP app from bots and scanners) | ||||
|     <LocationMatch "^/tkr/.*\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$"> | ||||
|         <RequireAll> | ||||
| <Directory "/var/www/tkr/templates"> | ||||
|     Require all denied | ||||
|         </RequireAll> | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # tkr application directory | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         Options -Indexes | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
| 
 | ||||
|         RewriteEngine On | ||||
| 
 | ||||
|         # Block direct PHP access | ||||
|         RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
|         RewriteRule ^.*$ - [R=404,L] | ||||
| 
 | ||||
|         # Serve the one static file that exists: css/tkr.css | ||||
|         # (Pass requests to css/custom/ through to the PHP app) | ||||
|         RewriteCond %{REQUEST_URI} !^/tkr/css/custom/ | ||||
|         RewriteRule ^css/tkr\.css$ css/tkr.css [L] | ||||
| 
 | ||||
|         # Send everything else to the front controller | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ index.php [L] | ||||
| </Directory> | ||||
| 
 | ||||
|     # Error and access logs | ||||
|     ErrorLog ${APACHE_LOG_DIR}/my-domain_error.log | ||||
|     CustomLog ${APACHE_LOG_DIR}/my-domain_access.log combined | ||||
| </VirtualHost> | ||||
|  | ||||
| @ -1,117 +1,51 @@ | ||||
| # Example nginx config | ||||
| # for serving tkr as a subdomain with SSL | ||||
| # e.g. https://tkr.my-domain.com/ | ||||
| # | ||||
| # Use SSL in production. | ||||
| # This is a minimal SSL confiuration | ||||
| # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ | ||||
| # Basic nginx config for tkr | ||||
| # Replace "your-domain.com" with your actual domain | ||||
| # Replace "/var/www/tkr" with your installation path | ||||
| 
 | ||||
| # HTTP - redirect to HTTPS | ||||
| server { | ||||
|     listen 80; | ||||
|     listen [::]:80; | ||||
|     server_name your-domain.com; | ||||
|     return 301 https://$host$request_uri; | ||||
| } | ||||
| 
 | ||||
| # HTTPS | ||||
| server { | ||||
|     listen 443 ssl; | ||||
|     listen [::]:443 ssl; | ||||
|      | ||||
|     # CONFIG: replace "localhost" with your subdomain (e.g. tkr.my-domain.com) | ||||
|     server_name localhost; | ||||
| 
 | ||||
|     # CONFIG: | ||||
|     # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|     server_name your-domain.com; | ||||
|     root /var/www/tkr/public; | ||||
|     index index.php; | ||||
|      | ||||
|     # CONFIG: | ||||
|     # Assumes you're using letsencrypt for cert generation | ||||
|     # Replace with the actual paths to your cert and key | ||||
|     ssl_certificate /etc/letsencrypt/live/tkr.my-domain.com/fullchain.pem; | ||||
|     ssl_certificate_key /etc/letsencrypt/live/tkr.my-domain.com/privkey.pem; | ||||
|     # SSL Configuration (using Let's Encrypt) | ||||
|     ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; | ||||
|     ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; | ||||
|      | ||||
|     # Security headers | ||||
|     # The first rule is to prevent including in a frame on a different domain. | ||||
|     # Remove it if you want to do that. | ||||
|     add_header X-Frame-Options "SAMEORIGIN" always; | ||||
|     add_header X-XSS-Protection "1; mode=block" always; | ||||
|     add_header X-Content-Type-Options "nosniff" always; | ||||
|     # Block access to sensitive directories | ||||
|     location ~ ^/(storage|src|templates|config) { | ||||
|         deny all; | ||||
|         return 404; | ||||
|     } | ||||
|      | ||||
|     # Deny access to hidden files | ||||
|     # Block access to hidden files | ||||
|     location ~ /\. { | ||||
|         deny all; | ||||
|         access_log off; | ||||
|         log_not_found off; | ||||
|     } | ||||
|      | ||||
|     # PHP routing - everything goes through index.php | ||||
|     # Front controller pattern - route everything through index.php | ||||
|     location / { | ||||
|         # Cache static files | ||||
|         # Note that I don't actually serve most of this (just css) | ||||
|         # but this prevents requests for static content from getting to the PHP handler. | ||||
|         # | ||||
|         # I've excluded /css/custom so that requests for uploaded css can be handled by the PHP app. | ||||
|         # That lets me store uploaded content outside of the document root, | ||||
|         # so it isn't served directly. | ||||
|         location ~* ^/(?!css/custom/).+\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|             expires 1y; | ||||
|             add_header Cache-Control "public, immutable"; | ||||
|             try_files $uri =404; | ||||
|         try_files $uri $uri/ @tkr; | ||||
|     } | ||||
|      | ||||
|         # index.php is the entry point | ||||
|         # It needs to be sent to php-fpm | ||||
|         # But if someone tries to directly access index.php, that file will throw a 404 | ||||
|         # so bots and scanners can't tell this is a php app | ||||
|         location = /index.php { | ||||
|             # CONFIG: | ||||
|             # If you're running php-fpm on the same server as nginx, | ||||
|             # then change this to the local php-fpm socket | ||||
|             # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|             fastcgi_pass php:9000; | ||||
| 
 | ||||
|             # CONFIG: | ||||
|             # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|     # Handle PHP requests | ||||
|     location @tkr { | ||||
|         fastcgi_pass unix:/run/php/php8.2-fpm.sock;  # Adjust PHP version as needed | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|         # Block attempts to access all other .php files directly | ||||
|         # (these are bots and scanners) | ||||
|         location ~ ^/.+\.php$ { | ||||
|             return 404; | ||||
|         } | ||||
| 
 | ||||
|         # forward other requests to the fallback block, | ||||
|         # which sends them to php-fpm for handling | ||||
|         try_files $uri $uri/ @tkr_fallback; | ||||
|     } | ||||
| 
 | ||||
|     # Fallback for /tkr routing - all non-file requests (e.g. /login) go to index.php | ||||
|     location @tkr_fallback { | ||||
|         # CONFIG: | ||||
|         # If you're running php-fpm on the same server as nginx, | ||||
|         # then change this to the local php-fpm socket | ||||
|         # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|         fastcgi_pass php:9000; | ||||
| 
 | ||||
|         # CONFIG: | ||||
|         # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|     # Deny access to sensitive directories | ||||
|     location ~ ^/(storage|src|templates|uploads|config) { | ||||
|         deny all; | ||||
|         return 404; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| server { | ||||
|     listen 80 default_server; | ||||
|     listen [::]:80 default_server; | ||||
| 
 | ||||
|     return 301 https://$host$request_uri; | ||||
| } | ||||
|  | ||||
| @ -1,118 +1,38 @@ | ||||
| # Example nginx config | ||||
| # for serving tkr as a subdfolder with SSL | ||||
| # e.g. https://my-domain.com/tkr | ||||
| # | ||||
| # Use SSL in production. | ||||
| # This is a minimal SSL confiuration | ||||
| # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ | ||||
| server { | ||||
|     listen 443 ssl; | ||||
|     listen [::]:443 ssl; | ||||
| # Basic nginx config for tkr in subfolder | ||||
| # e.g. https://your-domain.com/tkr | ||||
| # Add this location block to your existing server configuration | ||||
| 
 | ||||
|     # CONFIG: Replace localhost with your domain e.g. my-domain.com | ||||
|     server_name localhost; | ||||
| 
 | ||||
|     # CONFIG: | ||||
|     # Assumes you're using letsencrypt for cert generation | ||||
|     # Replace with the actual paths to your cert and key | ||||
|     ssl_certificate /etc/letsencrypt/live/my-domain.com/fullchain.pem; | ||||
|     ssl_certificate_key /etc/letsencrypt/live/my-domain.com/privkey.pem; | ||||
| 
 | ||||
|     # Security headers | ||||
|     # The first rule is to prevent including in a frame on a different domain. | ||||
|     # Remove it if you want to do that. | ||||
|     add_header X-Frame-Options "SAMEORIGIN" always; | ||||
|     add_header X-XSS-Protection "1; mode=block" always; | ||||
|     add_header X-Content-Type-Options "nosniff" always; | ||||
| 
 | ||||
|     # Deny access to hidden files | ||||
|     location ~ /\. { | ||||
|         deny all; | ||||
|         access_log off; | ||||
|         log_not_found off; | ||||
|     } | ||||
| 
 | ||||
|     # PHP routing - everything under /tkr goes through index.php | ||||
| location /tkr { | ||||
|         # CONFIG: | ||||
|         # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|     alias /var/www/tkr/public; | ||||
|     index index.php; | ||||
| 
 | ||||
|         # Cache static files | ||||
|         # Note that I don't actually serve most of this (just css) | ||||
|         # but this prevents requests for static content from getting to the PHP handler. | ||||
|         # | ||||
|         # I've excluded /css/custom so that requests for uploaded css can be handled by the PHP app. | ||||
|         # That lets me store uploaded content outside of the document root, | ||||
|         # so it isn't served directly. | ||||
|         location ~* ^/tkr/(?!css/custom/).+\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|             expires 1y; | ||||
|             add_header Cache-Control "public, immutable"; | ||||
|             try_files $uri =404; | ||||
|         } | ||||
| 
 | ||||
|         # index.php is the entry point | ||||
|         # It needs to be sent to php-fpm | ||||
|         # But if someone tries to directly access index.php, that file will throw a 404 | ||||
|         # so bots and scanners can't tell this is a php app | ||||
|         location = /tkr/index.php { | ||||
|             # CONFIG: | ||||
|             # If you're running php-fpm on the same server as nginx, | ||||
|             # then change this to the local php-fpm socket | ||||
|             # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|             fastcgi_pass php:9000; | ||||
| 
 | ||||
|             # CONFIG: | ||||
|             # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|     # Handle PHP files | ||||
|     location ~ \.php$ { | ||||
|         fastcgi_pass unix:/run/php/php8.2-fpm.sock;  # Adjust PHP version/socket as needed | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|             fastcgi_param REQUEST_METHOD $request_method; | ||||
|             fastcgi_param REQUEST_URI $request_uri; | ||||
|             fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|         # Block attempts to access all other .php files directly | ||||
|         # (these are bots and scanners) | ||||
|         location ~ ^/tkr/.+\.php$ { | ||||
|             return 404; | ||||
|         } | ||||
| 
 | ||||
|         # forward other requests to the fallback block, | ||||
|         # which sends them to php-fpm for handling | ||||
|         try_files $uri $uri/ @tkr_fallback; | ||||
|     } | ||||
| 
 | ||||
|     # Fallback for /tkr routing - all non-file requests (e.g. /login) go to index.php | ||||
|     location @tkr_fallback { | ||||
|         # CONFIG: | ||||
|         # If you're running php-fpm on the same server as nginx, | ||||
|         # then change this to the local php-fpm socket | ||||
|         # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|         fastcgi_pass php:9000; | ||||
| 
 | ||||
|         # CONFIG: | ||||
|         # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|     # Deny access to sensitive directories | ||||
|     location ~ ^/tkr/(storage|src|templates|uploads|config) { | ||||
|     # Block access to sensitive directories | ||||
|     location ~ ^/tkr/(storage|src|templates|config) { | ||||
|         deny all; | ||||
|         return 404; | ||||
|     } | ||||
| 
 | ||||
|     # Block access to hidden files | ||||
|     location ~ /\. { | ||||
|         deny all; | ||||
|     } | ||||
| 
 | ||||
| server { | ||||
|     listen 80 default_server; | ||||
|     listen [::]:80 default_server; | ||||
| 
 | ||||
|     return 301 https://$host$request_uri; | ||||
|     # Front controller pattern | ||||
|     try_files $uri $uri/ @tkr; | ||||
| } | ||||
| 
 | ||||
| location @tkr { | ||||
|     fastcgi_pass unix:/run/php/php8.2-fpm.sock;  # Adjust PHP version as needed | ||||
|     fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|     include fastcgi_params; | ||||
|     fastcgi_param REQUEST_METHOD $request_method; | ||||
|     fastcgi_param REQUEST_URI $request_uri; | ||||
|     fastcgi_param QUERY_STRING $query_string; | ||||
| } | ||||
							
								
								
									
										49
									
								
								examples/production/apache/.htaccess
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								examples/production/apache/.htaccess
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdirectory path | ||||
| # on shared hosting via .htaccess | ||||
| # | ||||
| # e.g. http://www.my-domain.com/tkr | ||||
| # | ||||
| # This should work without modification if you extract the app | ||||
| # to /tkr from your web document root | ||||
| 
 | ||||
| # Enable mod_rewrite | ||||
| RewriteEngine On | ||||
| 
 | ||||
| # Security headers | ||||
| Header always set X-Frame-Options "SAMEORIGIN" | ||||
| Header always set X-XSS-Protection "1; mode=block" | ||||
| Header always set X-Content-Type-Options "nosniff" | ||||
| 
 | ||||
| # Directory index | ||||
| DirectoryIndex public/index.php | ||||
| 
 | ||||
| # Security: Block direct access to .php files (except through rewrites) | ||||
| RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
| RewriteRule ^.*$ - [R=404,L] | ||||
| 
 | ||||
| # Security: Block access to sensitive directories | ||||
| RewriteRule ^(storage|src|templates|examples|config)(/.*)?$ - [F,L] | ||||
| 
 | ||||
| # Security: Block access to hidden files | ||||
| RewriteRule ^\..*$ - [F,L] | ||||
| 
 | ||||
| # Cache CSS files for 1 hour | ||||
| <FilesMatch "\.css$"> | ||||
|     Header set Cache-Control "public, max-age=3600" | ||||
| </FilesMatch> | ||||
| 
 | ||||
| # Serve the one static file that exists: css/default.css | ||||
| # (Pass requests to css/custom/ through to the PHP app) | ||||
| RewriteCond %{REQUEST_URI} !^/css/custom/ | ||||
| RewriteRule ^css/default\.css$ public/css/default.css [L] | ||||
| 
 | ||||
| # 404 all other static files (images, js, fonts, etc.) | ||||
| # so those requests don't hit the PHP app | ||||
| # (this is to reduce load on the PHP app from bots and scanners) | ||||
| RewriteRule \.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$ - [R=404,L] | ||||
| 
 | ||||
| # Everything else goes to the front controller | ||||
| RewriteCond %{REQUEST_FILENAME} !-f | ||||
| RewriteCond %{REQUEST_FILENAME} !-d | ||||
| RewriteRule ^(.*)$ public/index.php [L] | ||||
							
								
								
									
										91
									
								
								examples/production/apache/subfolder.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								examples/production/apache/subfolder.conf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdirectory path with SSL | ||||
| # e.g. https://www.my-domain.com/tkr | ||||
| # | ||||
| # Use SSL in production. | ||||
| # This is a minimal SSL confiuration | ||||
| # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ | ||||
| <VirtualHost *:80> | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName localhost | ||||
|     # CONFIG: Replace  with your subdomain, e.g. tkr.my-domain.com | ||||
|     DocumentRoot /var/www/tkr | ||||
|     # Redirect HTTP to HTTPS | ||||
|     Redirect permanent / https://my-domain.com/ | ||||
| </VirtualHost> | ||||
| 
 | ||||
| <VirtualHost *:443> | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName localhost | ||||
|     # CONFIG: Replace  with your subdomain, e.g. tkr.my-domain.com | ||||
|     DocumentRoot /var/www/tkr/ | ||||
| 
 | ||||
|     # SSL Configuration | ||||
|     SSLEngine on | ||||
| 
 | ||||
|     # Assumes you're using letsencrypt for cert generation | ||||
|     # Replace with the actual paths to your cert and key | ||||
|     SSLCertificateFile /etc/letsencrypt/live/my-domain.com/fullchain.pem | ||||
|     SSLCertificateKeyFile /etc/letsencrypt/live/my-domain.com/privkey.pem | ||||
| 
 | ||||
|     # Security headers | ||||
|     Header always set X-Frame-Options "SAMEORIGIN" | ||||
|     Header always set X-XSS-Protection "1; mode=block" | ||||
|     Header always set X-Content-Type-Options "nosniff" | ||||
|     Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" | ||||
| 
 | ||||
|     # tkr Application at /tkr | ||||
|     # NOTE: If you change the directory name, | ||||
|     # remember to update all instances of /var/www/tkr in this file to match | ||||
|     Alias /tkr /var/www/tkr/public | ||||
| 
 | ||||
|     # Block access to sensitive TKR directories | ||||
|     <Directory "/var/www/tkr/storage"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/src"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/config"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
| 
 | ||||
|     # 404 all non-css static files in /tkr (images, js, fonts, etc.) | ||||
|     # so those requests don't hit the PHP app | ||||
|     # (this is to reduce load on the PHP app from bots and scanners) | ||||
|     <LocationMatch "^/tkr/.*\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$"> | ||||
|         <RequireAll> | ||||
|             Require all denied | ||||
|         </RequireAll> | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # tkr application directory | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         Options -Indexes | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
| 
 | ||||
|         RewriteEngine On | ||||
| 
 | ||||
|         # Block direct PHP access | ||||
|         RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
|         RewriteRule ^.*$ - [R=404,L] | ||||
| 
 | ||||
|         # Serve the one static file that exists: css/default.css | ||||
|         # (Pass requests to css/custom/ through to the PHP app) | ||||
|         RewriteCond %{REQUEST_URI} !^/tkr/css/custom/ | ||||
|         RewriteRule ^css/default\.css$ css/tkr.css [L] | ||||
| 
 | ||||
|         # Send everything else to the front controller | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ index.php [L] | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Error and access logs | ||||
|     ErrorLog ${APACHE_LOG_DIR}/my-domain_error.log | ||||
|     CustomLog ${APACHE_LOG_DIR}/my-domain_access.log combined | ||||
| </VirtualHost> | ||||
							
								
								
									
										99
									
								
								examples/production/apache/tkr.my-domain.com.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								examples/production/apache/tkr.my-domain.com.conf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| # Example Apache VirtualHost | ||||
| # for serving tkr as a subdomain root with SSL | ||||
| # e.g. https://tkr.my-domain.com/ | ||||
| # | ||||
| # Use SSL in production. | ||||
| # This is a minimal SSL confiuration | ||||
| # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ | ||||
| <VirtualHost *:80> | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName localhost | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     DocumentRoot /var/www/tkr/public | ||||
|     # Redirect HTTP to HTTPS | ||||
|     Redirect permanent / https://tkr.my-domain.com/ | ||||
| </VirtualHost> | ||||
| 
 | ||||
| <VirtualHost *:443> | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     ServerName localhost | ||||
|     # CONFIG: Replace localhost with your subdomain, e.g. tkr.my-domain.com | ||||
|     DocumentRoot /var/www/tkr/public | ||||
| 
 | ||||
|     # SSL Configuration | ||||
|     SSLEngine on | ||||
| 
 | ||||
|     # Assumes you're using letsencrypt for cert generation | ||||
|     # Replace with the actual paths to your cert and key | ||||
|     SSLCertificateFile /etc/letsencrypt/live/tkr.my-domain.com/fullchain.pem | ||||
|     SSLCertificateKeyFile /etc/letsencrypt/live/tkr.my-domain.com/privkey.pem | ||||
| 
 | ||||
|     # Security headers | ||||
|     Header always set X-Frame-Options "SAMEORIGIN" | ||||
|     Header always set X-XSS-Protection "1; mode=block" | ||||
|     Header always set X-Content-Type-Options "nosniff" | ||||
|     Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" | ||||
| 
 | ||||
|     # Block access to sensitive directories | ||||
|     <Directory "/var/www/tkr/storage"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/src"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/templates"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
|     <Directory "/var/www/tkr/config"> | ||||
|         Require all denied | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Block access to hidden files | ||||
|     <DirectoryMatch "^\.|/\."> | ||||
|         Require all denied | ||||
|     </DirectoryMatch> | ||||
| 
 | ||||
|     # Cache CSS files | ||||
|     <LocationMatch "\.css$"> | ||||
|         Header set Cache-Control "public, max-age=3600" | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # Serve static CSS file | ||||
|     Alias /css/tkr.css /var/www/tkr/public/css/tkr.css | ||||
| 
 | ||||
|     # 404 all non-css static files (images, js, fonts, etc.) | ||||
|     # so those requests don't hit the PHP app | ||||
|     # (this is to reduce load on the PHP app from bots and scanners) | ||||
|     <LocationMatch "\.(js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip|mp3|mp4|avi|mov)$"> | ||||
|         <RequireAll> | ||||
|             Require all denied | ||||
|         </RequireAll> | ||||
|     </LocationMatch> | ||||
| 
 | ||||
|     # Enable rewrite engine | ||||
|     <Directory "/var/www/tkr/public"> | ||||
|         Options -Indexes | ||||
|         AllowOverride None | ||||
|         Require all granted | ||||
| 
 | ||||
|         RewriteEngine On | ||||
| 
 | ||||
|         # Block direct PHP access | ||||
|         RewriteCond %{THE_REQUEST} \s/[^?\s]*\.php[\s?] [NC] | ||||
|         RewriteRule ^.*$ - [R=404,L] | ||||
| 
 | ||||
|         # Serve the one static file that exists: css/default.css | ||||
|         # (Pass requests to css/custom/ through to the PHP app) | ||||
|         RewriteCond %{REQUEST_URI} !^/css/custom/ | ||||
|         RewriteRule ^css/default\.css$ css/default.css [L] | ||||
| 
 | ||||
|         # Everything else to front controller | ||||
|         RewriteCond %{REQUEST_FILENAME} !-f | ||||
|         RewriteCond %{REQUEST_FILENAME} !-d | ||||
|         RewriteRule ^(.*)$ index.php [L] | ||||
|     </Directory> | ||||
| 
 | ||||
|     # Error and access logs | ||||
|     ErrorLog ${APACHE_LOG_DIR}/tkr_error.log | ||||
|     CustomLog ${APACHE_LOG_DIR}/tkr_access.log combined | ||||
| </VirtualHost> | ||||
							
								
								
									
										117
									
								
								examples/production/nginx/nginx.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								examples/production/nginx/nginx.conf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,117 @@ | ||||
| # Example nginx config | ||||
| # for serving tkr as a subdomain with SSL | ||||
| # e.g. https://tkr.my-domain.com/ | ||||
| # | ||||
| # Use SSL in production. | ||||
| # This is a minimal SSL confiuration | ||||
| # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ | ||||
| server { | ||||
|     listen 443 ssl; | ||||
|     listen [::]:443 ssl; | ||||
| 
 | ||||
|     # CONFIG: replace "localhost" with your subdomain (e.g. tkr.my-domain.com) | ||||
|     server_name localhost; | ||||
| 
 | ||||
|     # CONFIG: | ||||
|     # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|     root /var/www/tkr/public; | ||||
|     index index.php; | ||||
| 
 | ||||
|     # CONFIG: | ||||
|     # Assumes you're using letsencrypt for cert generation | ||||
|     # Replace with the actual paths to your cert and key | ||||
|     ssl_certificate /etc/letsencrypt/live/tkr.my-domain.com/fullchain.pem; | ||||
|     ssl_certificate_key /etc/letsencrypt/live/tkr.my-domain.com/privkey.pem; | ||||
| 
 | ||||
|     # Security headers | ||||
|     # The first rule is to prevent including in a frame on a different domain. | ||||
|     # Remove it if you want to do that. | ||||
|     add_header X-Frame-Options "SAMEORIGIN" always; | ||||
|     add_header X-XSS-Protection "1; mode=block" always; | ||||
|     add_header X-Content-Type-Options "nosniff" always; | ||||
| 
 | ||||
|     # Deny access to hidden files | ||||
|     location ~ /\. { | ||||
|         deny all; | ||||
|         access_log off; | ||||
|         log_not_found off; | ||||
|     } | ||||
| 
 | ||||
|     # PHP routing - everything goes through index.php | ||||
|     location / { | ||||
|         # Cache static files | ||||
|         # Note that I don't actually serve most of this (just css) | ||||
|         # but this prevents requests for static content from getting to the PHP handler. | ||||
|         # | ||||
|         # I've excluded /css/custom so that requests for uploaded css can be handled by the PHP app. | ||||
|         # That lets me store uploaded content outside of the document root, | ||||
|         # so it isn't served directly. | ||||
|         location ~* ^/(?!css/custom/).+\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|             expires 1y; | ||||
|             add_header Cache-Control "public, immutable"; | ||||
|             try_files $uri =404; | ||||
|         } | ||||
| 
 | ||||
|         # index.php is the entry point | ||||
|         # It needs to be sent to php-fpm | ||||
|         # But if someone tries to directly access index.php, that file will throw a 404 | ||||
|         # so bots and scanners can't tell this is a php app | ||||
|         location = /index.php { | ||||
|             # CONFIG: | ||||
|             # If you're running php-fpm on the same server as nginx, | ||||
|             # then change this to the local php-fpm socket | ||||
|             # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|             fastcgi_pass php:9000; | ||||
| 
 | ||||
|             # CONFIG: | ||||
|             # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|             fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|             include fastcgi_params; | ||||
| 
 | ||||
|             fastcgi_param REQUEST_METHOD $request_method; | ||||
|             fastcgi_param REQUEST_URI $request_uri; | ||||
|             fastcgi_param QUERY_STRING $query_string; | ||||
|         } | ||||
| 
 | ||||
|         # Block attempts to access all other .php files directly | ||||
|         # (these are bots and scanners) | ||||
|         location ~ ^/.+\.php$ { | ||||
|             return 404; | ||||
|         } | ||||
| 
 | ||||
|         # forward other requests to the fallback block, | ||||
|         # which sends them to php-fpm for handling | ||||
|         try_files $uri $uri/ @tkr_fallback; | ||||
|     } | ||||
| 
 | ||||
|     # Fallback for /tkr routing - all non-file requests (e.g. /login) go to index.php | ||||
|     location @tkr_fallback { | ||||
|         # CONFIG: | ||||
|         # If you're running php-fpm on the same server as nginx, | ||||
|         # then change this to the local php-fpm socket | ||||
|         # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|         fastcgi_pass php:9000; | ||||
| 
 | ||||
|         # CONFIG: | ||||
|         # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|     # Deny access to sensitive directories | ||||
|     location ~ ^/(storage|src|templates|uploads|config) { | ||||
|         deny all; | ||||
|         return 404; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| server { | ||||
|     listen 80 default_server; | ||||
|     listen [::]:80 default_server; | ||||
| 
 | ||||
|     return 301 https://$host$request_uri; | ||||
| } | ||||
							
								
								
									
										118
									
								
								examples/production/nginx/subfolder.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								examples/production/nginx/subfolder.conf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,118 @@ | ||||
| # Example nginx config | ||||
| # for serving tkr as a subdfolder with SSL | ||||
| # e.g. https://my-domain.com/tkr | ||||
| # | ||||
| # Use SSL in production. | ||||
| # This is a minimal SSL confiuration | ||||
| # For more robust SSL configuration, refer to https://ssl-config.mozilla.org/ | ||||
| server { | ||||
|     listen 443 ssl; | ||||
|     listen [::]:443 ssl; | ||||
| 
 | ||||
|     # CONFIG: Replace localhost with your domain e.g. my-domain.com | ||||
|     server_name localhost; | ||||
| 
 | ||||
|     # CONFIG: | ||||
|     # Assumes you're using letsencrypt for cert generation | ||||
|     # Replace with the actual paths to your cert and key | ||||
|     ssl_certificate /etc/letsencrypt/live/my-domain.com/fullchain.pem; | ||||
|     ssl_certificate_key /etc/letsencrypt/live/my-domain.com/privkey.pem; | ||||
| 
 | ||||
|     # Security headers | ||||
|     # The first rule is to prevent including in a frame on a different domain. | ||||
|     # Remove it if you want to do that. | ||||
|     add_header X-Frame-Options "SAMEORIGIN" always; | ||||
|     add_header X-XSS-Protection "1; mode=block" always; | ||||
|     add_header X-Content-Type-Options "nosniff" always; | ||||
| 
 | ||||
|     # Deny access to hidden files | ||||
|     location ~ /\. { | ||||
|         deny all; | ||||
|         access_log off; | ||||
|         log_not_found off; | ||||
|     } | ||||
| 
 | ||||
|     # PHP routing - everything under /tkr goes through index.php | ||||
|     location /tkr { | ||||
|         # CONFIG: | ||||
|         # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|         alias /var/www/tkr/public; | ||||
|         index index.php; | ||||
| 
 | ||||
|         # Cache static files | ||||
|         # Note that I don't actually serve most of this (just css) | ||||
|         # but this prevents requests for static content from getting to the PHP handler. | ||||
|         # | ||||
|         # I've excluded /css/custom so that requests for uploaded css can be handled by the PHP app. | ||||
|         # That lets me store uploaded content outside of the document root, | ||||
|         # so it isn't served directly. | ||||
|         location ~* ^/tkr/(?!css/custom/).+\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { | ||||
|             expires 1y; | ||||
|             add_header Cache-Control "public, immutable"; | ||||
|             try_files $uri =404; | ||||
|         } | ||||
| 
 | ||||
|         # index.php is the entry point | ||||
|         # It needs to be sent to php-fpm | ||||
|         # But if someone tries to directly access index.php, that file will throw a 404 | ||||
|         # so bots and scanners can't tell this is a php app | ||||
|         location = /tkr/index.php { | ||||
|             # CONFIG: | ||||
|             # If you're running php-fpm on the same server as nginx, | ||||
|             # then change this to the local php-fpm socket | ||||
|             # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|             fastcgi_pass php:9000; | ||||
| 
 | ||||
|             # CONFIG: | ||||
|             # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|             fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|             include fastcgi_params; | ||||
| 
 | ||||
|             fastcgi_param REQUEST_METHOD $request_method; | ||||
|             fastcgi_param REQUEST_URI $request_uri; | ||||
|             fastcgi_param QUERY_STRING $query_string; | ||||
|         } | ||||
| 
 | ||||
|         # Block attempts to access all other .php files directly | ||||
|         # (these are bots and scanners) | ||||
|         location ~ ^/tkr/.+\.php$ { | ||||
|             return 404; | ||||
|         } | ||||
| 
 | ||||
|         # forward other requests to the fallback block, | ||||
|         # which sends them to php-fpm for handling | ||||
|         try_files $uri $uri/ @tkr_fallback; | ||||
|     } | ||||
| 
 | ||||
|     # Fallback for /tkr routing - all non-file requests (e.g. /login) go to index.php | ||||
|     location @tkr_fallback { | ||||
|         # CONFIG: | ||||
|         # If you're running php-fpm on the same server as nginx, | ||||
|         # then change this to the local php-fpm socket | ||||
|         # e.g. fastcgi_pass unix:/run/php/php8.2-fpm.sock; | ||||
|         fastcgi_pass php:9000; | ||||
| 
 | ||||
|         # CONFIG: | ||||
|         # replace "/var/www/tkr" with the directory you extracted the .zip file to (if different) | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         fastcgi_param SCRIPT_FILENAME /var/www/tkr/public/index.php; | ||||
|         include fastcgi_params; | ||||
| 
 | ||||
|         fastcgi_param REQUEST_METHOD $request_method; | ||||
|         fastcgi_param REQUEST_URI $request_uri; | ||||
|         fastcgi_param QUERY_STRING $query_string; | ||||
|     } | ||||
| 
 | ||||
|     # Deny access to sensitive directories | ||||
|     location ~ ^/tkr/(storage|src|templates|uploads|config) { | ||||
|         deny all; | ||||
|         return 404; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| server { | ||||
|     listen 80 default_server; | ||||
|     listen [::]:80 default_server; | ||||
| 
 | ||||
|     return 301 https://$host$request_uri; | ||||
| } | ||||
| @ -50,7 +50,7 @@ class AdminController extends Controller { | ||||
|         } | ||||
| 
 | ||||
|         $result = $this->saveSettings($_POST, false); | ||||
|         header('Location: ' . $_SERVER['PHP_SELF']); | ||||
|         header('Location: ' . $_SERVER['REQUEST_URI']); | ||||
|         exit; | ||||
|     } | ||||
| 
 | ||||
| @ -58,7 +58,7 @@ class AdminController extends Controller { | ||||
|         // for setup, we don't care if they're logged in
 | ||||
|         // (because they can't be until setup is complete)
 | ||||
|         $result = $this->saveSettings($_POST, true); | ||||
|         header('Location: ' . $_SERVER['PHP_SELF']); | ||||
|         header('Location: ' . $_SERVER['REQUEST_URI']); | ||||
|         exit; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -39,7 +39,7 @@ class AuthController extends Controller { | ||||
|                     } catch (Exception $e) { | ||||
|                         Log::error("Failed to create login session for {$username}: " . $e->getMessage()); | ||||
|                         Session::setFlashMessage('error', 'Login failed - session error'); | ||||
|                         header('Location: ' . $_SERVER['PHP_SELF']); | ||||
|                         header('Location: ' . $_SERVER['REQUEST_URI']); | ||||
|                         exit; | ||||
|                     } | ||||
|                 } else { | ||||
| @ -47,13 +47,13 @@ class AuthController extends Controller { | ||||
| 
 | ||||
|                     // Set a flash message and reload the login page
 | ||||
|                     Session::setFlashMessage('error', 'Invalid username or password'); | ||||
|                     header('Location: ' . $_SERVER['PHP_SELF']); | ||||
|                     header('Location: ' . $_SERVER['REQUEST_URI']); | ||||
|                     exit; | ||||
|                 } | ||||
|             } catch (Exception $e) { | ||||
|                 Log::error("Database error during login for {$username}: " . $e->getMessage()); | ||||
|                 Session::setFlashMessage('error', 'Login temporarily unavailable'); | ||||
|                 header('Location: ' . $_SERVER['PHP_SELF']); | ||||
|                 header('Location: ' . $_SERVER['REQUEST_URI']); | ||||
|                 exit; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @ -20,32 +20,54 @@ class CssController extends Controller { | ||||
|         global $app; | ||||
|         $cssModel = new CssModel($app['db']); | ||||
|         $filename = "$baseFilename.css"; | ||||
|         Log::debug("Attempting to serve custom css: {$filename}"); | ||||
| 
 | ||||
|         // Make sure the file exists in the database
 | ||||
|         $cssRow = $cssModel->getByFilename($filename); | ||||
| 
 | ||||
|         if (!$cssRow){ | ||||
|             http_response_code(404); | ||||
|             exit("CSS file not found: $filename"); | ||||
|             Log::error("Custom css file not in database: {$filename}"); | ||||
|             exit; | ||||
|         } | ||||
| 
 | ||||
|         // Make sure the file exists on the filesystem and is readable
 | ||||
|         $filePath = CSS_UPLOAD_DIR . "/$filename"; | ||||
| 
 | ||||
|         if (!file_exists($filePath) || !is_readable($filePath)) { | ||||
|             http_response_code(404); | ||||
|             exit("CSS file not found: $filePath"); | ||||
|             Log::error("Custom css file not found or not readable: $filePath"); | ||||
|             exit; | ||||
|         } | ||||
| 
 | ||||
|         // This shouldn't be possible, but I'm being extra paranoid
 | ||||
|         // about user input
 | ||||
|         // Make sure the file has a .css extension
 | ||||
|         $ext = strToLower(pathinfo($filename, PATHINFO_EXTENSION)); | ||||
|         if($ext != 'css'){ | ||||
|             http_response_code(400); | ||||
|             exit("Invalid file type requested: $ext"); | ||||
|             Log::error("Invalid file type requested: $ext"); | ||||
|             exit; | ||||
|         } | ||||
| 
 | ||||
|         // If we get here, serve the file
 | ||||
|         Log::debug("Serving custom css: {$filename}"); | ||||
|         header('Content-type: text/css'); | ||||
|         header('Cache-control: public, max-age=3600'); | ||||
|         readfile($filePath); | ||||
|         exit; | ||||
|     } | ||||
| 
 | ||||
|     public function serveDefaultCss(){ | ||||
|         $filePath = PUBLIC_DIR . '/css/default.css'; | ||||
|         Log::debug("Serving default css: {$filePath}"); | ||||
| 
 | ||||
|         // Make sure the default CSS file exists and is readable
 | ||||
|         if (!file_exists($filePath) || !is_readable($filePath)) { | ||||
|             http_response_code(404); | ||||
|             Log::error("Default CSS file not found"); | ||||
|             exit; | ||||
|         } | ||||
| 
 | ||||
|         //  Serve the file
 | ||||
|         header('Content-type: text/css'); | ||||
|         header('Cache-control: public, max-age=3600'); | ||||
|         readfile($filePath); | ||||
|         exit; | ||||
|     } | ||||
| @ -64,7 +86,7 @@ class CssController extends Controller { | ||||
|         } | ||||
| 
 | ||||
|         // redirect after handling to avoid resubmitting form
 | ||||
|         header('Location: ' . $_SERVER['PHP_SELF']); | ||||
|         header('Location: ' . $_SERVER['REQUEST_URI']); | ||||
|         exit; | ||||
|     } | ||||
| 
 | ||||
| @ -129,7 +151,7 @@ class CssController extends Controller { | ||||
|         try { | ||||
|             if ($_POST['selectCssFile']){ | ||||
|                 // Set custom theme
 | ||||
|                 $app['settings']->cssId = $_POST['selectCssFile']; | ||||
|                 $app['settings']->cssId = (int)($_POST['selectCssFile']); | ||||
|             } else { | ||||
|                 // Set default theme
 | ||||
|                 $app['settings']->cssId = null; | ||||
|  | ||||
| @ -27,6 +27,7 @@ class Router { | ||||
|         ['tick/{id}', 'TickController'], | ||||
|         ['tick/{id}/delete', 'TickController@handleDelete', ['POST']], | ||||
|         ['css/custom/{filename}.css', 'CssController@serveCustomCss'], | ||||
|         ['css/default.css', 'CssController@serveDefaultCss'], | ||||
|     ]; | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user