9.0 KiB
Subdirectory Deployment Guide
This guide explains how to deploy the CGW Product Finder to a subdirectory on your web server (e.g., http://example.com/cgwproducts/).
🎯 Overview
The application is now configured to support subdirectory deployments through the APPLICATION_ROOT configuration variable. All templates use relative paths and url_for() to ensure proper routing regardless of deployment location.
🛠️ Configuration
Method 1: Environment Variable (Recommended for Production)
Set the APPLICATION_ROOT environment variable before starting the application:
Linux/Mac (Apache with Passenger):
export APPLICATION_ROOT="/cgwproducts"
Windows (IIS): Add to web.config or set in IIS environment variables:
APPLICATION_ROOT=/cgwproducts
Apache .htaccess or Virtual Host:
SetEnv APPLICATION_ROOT /cgwproducts
Method 2: Modify config.py
Edit app/config.py and change the APPLICATION_ROOT line:
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'your-secret-here'
# Change this line to your subdirectory path
APPLICATION_ROOT = '/cgwproducts' # Or whatever your path is
Important: The path should:
- Start with
/ - NOT end with
/ - Match your web server configuration
Method 3: Server Configuration
Apache with Passenger
If deploying to http://example.com/cgwproducts/:
<VirtualHost *:80>
ServerName example.com
# Document root is one level up from app folder
DocumentRoot /path/to/CGW Product Finder
# Set subdirectory as alias to app folder
Alias /cgwproducts /path/to/CGW Product Finder/app
<Directory "/path/to/CGW Product Finder/app">
Allow from all
Options -MultiViews
# Set APPLICATION_ROOT environment variable
SetEnv APPLICATION_ROOT /cgwproducts
# Enable Passenger
PassengerEnabled on
PassengerAppRoot /path/to/CGW Product Finder/app
PassengerPython /path/to/python3
</Directory>
# Block access to admin and data folders
<Directory "/path/to/CGW Product Finder/app/admin">
Require all denied
</Directory>
<Directory "/path/to/CGW Product Finder/app/data">
# Allow access only through Flask API
<FilesMatch "\\.json$">
Require all denied
</FilesMatch>
</Directory>
</VirtualHost>
Nginx with uWSGI
server {
listen 80;
server_name example.com;
location /cgwproducts {
# Strip the /cgwproducts prefix when passing to Flask
rewrite ^/cgwproducts(.*)$ $1 break;
include uwsgi_params;
uwsgi_pass unix:/tmp/cgw-product-finder.sock;
# Set APPLICATION_ROOT
uwsgi_param APPLICATION_ROOT /cgwproducts;
}
# Block admin folder
location /cgwproducts/admin {
deny all;
}
}
📝 Python 3.13.11 Considerations
For Python 3.13.11, some packages may not have pre-built wheels yet.
Updated requirements.txt
The requirements.txt has been updated to make Pillow optional:
Flask>=3.0.0
Werkzeug>=3.0.0
# Pillow>=10.0.0 # Optional - only for image generation
Installation Steps
# Upgrade pip first
python -m pip install --upgrade pip
# Install core requirements (will work without Pillow)
pip install Flask>=3.0.0 Werkzeug>=3.0.0
# Try to install Pillow (optional)
pip install Pillow
# If Pillow fails, the app will still work but disable image generation
Note: Pillow build errors on Python 3.13.11 are common. If you don't need dynamic image generation, you can skip it.
✅ Testing Your Deployment
Step 1: Verify Configuration
Check that APPLICATION_ROOT is set correctly:
# Run in Python console
import os
print(os.environ.get('APPLICATION_ROOT', '/'))
Step 2: Test Routes
If deployed to /cgwproducts/, test these URLs:
- ✅
http://example.com/cgwproducts/→ Should redirect to login - ✅
http://example.com/cgwproducts/login→ Should show login page - ✅
http://example.com/cgwproducts/api/session→ Should return JSON - ✅
http://example.com/cgwproducts/css/styles.css→ Should load CSS - ✅
http://example.com/cgwproducts/js/script.js→ Should load JS - ✅
http://example.com/cgwproducts/data/products.json→ Should load data
Step 3: Test Login Flow
- Go to
/cgwproducts/login - Login with Master / Master
- Should redirect to
/cgwproducts/select-location - Select a location
- Should redirect to
/cgwproducts/ - User info should display in header
- Click logout
- Should return to
/cgwproducts/login
Step 4: Test User Management
- Login as Master
- On location selection page, click "User Management"
- Should go to
/cgwproducts/users - All buttons should work (Add User, Change Password, etc.)
🔧 Troubleshooting
Issue: 404 on CSS/JS files
Cause: Static files not being served correctly
Fix: Ensure Flask routes for /css/, /js/, /data/ are working:
# Test directly
curl http://example.com/cgwproducts/css/styles.css
curl http://example.com/cgwproducts/js/script.js
Issue: Login redirects to wrong path
Cause: APPLICATION_ROOT not set or incorrect
Fix:
- Check environment variable:
echo $APPLICATION_ROOT - Verify it matches your URL path
- Restart web server after changing
Issue: API calls return 404
Cause: API routes need APPLICATION_ROOT prefix
Fix: All templates now use BASE_URL variable:
const BASE_URL = '{{ base_url }}'; // Automatically set by Flask
fetch(BASE_URL + '/api/login', {...})
Issue: Cannot access /users or other protected pages
Cause: Session not persisting across requests
Fix:
- Verify SECRET_KEY is set and doesn't change between restarts
- Check cookie settings (SESSION_COOKIE_PATH should match APPLICATION_ROOT)
- Ensure browser accepts cookies from subdirectory
Issue: Module import errors after pip install
Cause: Pillow build failed on Python 3.13.11
Fix: Pillow is now optional. Application will work without it:
# Install without Pillow
pip install Flask>=3.0.0 Werkzeug>=3.0.0
# App will show: "Image generation not available"
# But all other features work
📂 Files Modified for Subdirectory Support
The following files have been updated to support subdirectory deployments:
Backend:
app/config.py- Added APPLICATION_ROOT configurationapp/app.py- Added context processor for base_urlapp/requirements.txt- Made Pillow optional
Templates (use {{ base_url }} and {{ url_for() }}):
app/templates/login.htmlapp/templates/select_location.htmlapp/templates/user_manager.htmlapp/templates/index2.htmlapp/templates/access_denied.html
JavaScript Updates:
All templates now define BASE_URL at the top of their scripts:
const BASE_URL = '{{ base_url }}';
All fetch calls use: fetch(BASE_URL + '/api/endpoint', ...)
🚀 Deployment Checklist
Before deploying to a subdirectory:
- Set APPLICATION_ROOT environment variable or update config.py
- Install Flask and Werkzeug:
pip install Flask>=3.0.0 Werkzeug>=3.0.0 - (Optional) Install Pillow:
pip install Pillow - Upload all modified files to server
- Configure web server (Apache/Nginx) with subdirectory path
- Set secure SECRET_KEY in production
- Block public access to /admin/ and /data/ folders
- Test all routes with subdirectory prefix
- Test login flow and session persistence
- Verify CSS/JS/images load correctly
- Test API endpoints return correct responses
📞 Need Help?
Common deployment paths:
- Root:
/(default, no configuration needed) - Application subdirectory:
/cgwproducts - User subdirectory:
/~username/cgwproducts - Domain subdirectory:
/app
Whatever path you choose, set it as APPLICATION_ROOT and ensure your web server passes requests to Flask with that prefix.
🔐 Security Notes
When deploying to a subdirectory:
- SECRET_KEY - Must be set and persistent across restarts
- Session Cookies - Will be scoped to the subdirectory path
- Admin Folder - Must be blocked from web access
- Data Folder - JSON files should only be accessible through API
- HTTPS - Use SSL/TLS in production and set SESSION_COOKIE_SECURE = True
✨ Benefits of This Approach
- ✅ Deploy to any path without code changes
- ✅ Works at root
/or subdirectory/cgwproducts/ - ✅ All routes automatically adjust to deployment path
- ✅ No hardcoded URLs in templates or JavaScript
- ✅ Compatible with Apache, Nginx, IIS
- ✅ Passenger and uWSGI compatible
- ✅ Works with Python 3.13.11 (Pillow optional)