Breaking Changes in V2
Most V1 deployments will upgrade smoothly to V2, but there are some important changes you should know about. This page documents breaking changes and how to handle them.
⚠️ Impact Summary
| Change | Impact | Action Required |
|---|---|---|
| Template Customization | High | Rewrite customizations |
| UI Settings Location | Medium | Use in-app settings |
| Session Management | Low | Update setting names |
| Database Notifications | Low | Use audit logs instead |
🎨 Template Customization System Removed
Impact: HIGH for users who customized UI using customFiles/templates/
What Changed
V1 Approach:
customFiles/
└── templates/
├── fragments/
│ └── navbar.html # Custom navbar
└── home.html # Custom homepage
V1 used server-side template injection with Thymeleaf templates.
V2 Approach: V2 uses React frontend - server-side template injection no longer possible.
Migration Path
If you customized templates in V1, you have two options:
Option 1: Use Built-In Customization (Recommended)
V2 provides in-app settings for most common customizations:
Available Customizations:
- App name and description
- Navbar branding
- Logo style (classic/modern)
- Custom logo upload
- Homepage description
How to use:
- Enable login:
SECURITY_ENABLELOGIN=true - Log in as admin
- Go to Settings → UI
- Configure branding there
Learn more: UI Customisation
Option 2: Edit Static Files in Docker
For customizations beyond built-in settings, you can mount and edit static files:
Steps:
- Mount the
/customFiles/static/directory in Docker - Add your custom static files (images, favicons, etc.)
- Reference them in your HTML/settings
- Restart container to apply changes
Example Docker compose:
volumes:
- ./customFiles:/customFiles:rw
Use cases:
- Custom favicon
- Custom images/logos
- Static assets
Option 3: Fork the Frontend (Advanced)
For complete UI customization:
Steps:
- Fork Stirling-PDF repository
- Modify React components in
frontend/src/ - Build custom frontend
- Deploy in split mode with custom frontend
Trade-offs:
- ✅ Complete control
- ❌ Must maintain your fork
- ❌ Manual merges for updates
What No Longer Works
These V1 customization patterns are no longer supported:
<!-- V1: Inject custom navbar (NO LONGER WORKS) -->
<div th:replace="fragments/navbar :: navbar"></div>
<!-- V1: Conditional content (NO LONGER WORKS) -->
<div th:if="${@propertyService.get('ui.showAdvanced')}">
Custom content
</div>
<!-- V1: Server-side variables (NO LONGER WORKS) -->
<span th:text="${appName}"></span>
⚙️ UI Settings Moved to In-App Configuration
Impact: MEDIUM - Settings moved, but easy to reconfigure
What Changed
V1 Configuration:
ui:
appName: 'My PDF Tool'
homeDescription: 'Welcome to our PDF service!'
V2 Configuration:
ui:
appNameNavbar: 'My PDF Tool' # Still in YAML
# appName and homeDescription REMOVED
# Configure these in-app instead
Why the Change
Benefits:
- ✅ No container restart needed
- ✅ Visual interface with preview
- ✅ Validation prevents errors
- ✅ Changes apply immediately
- ✅ Role-based access control
Migration Steps
-
Note your current settings:
# From V1 settings.yml
ui:
appName: 'CompanyName PDF'
homeDescription: 'Internal document processing' -
Remove from settings.yml:
ui:
appNameNavbar: 'CompanyName PDF'
# appName - REMOVE THIS LINE
# homeDescription - REMOVE THIS LINE -
Configure in UI:
- Enable login:
SECURITY_ENABLELOGIN=true - Start V2
- Log in as admin
- Go to Settings → UI
- Enter app name and description
- Save
- Enable login:
Environment Variables
These environment variables no longer work:
# V1 (NO LONGER WORKS)
UI_APPNAME="My PDF Tool"
UI_HOMEDESCRIPTION="Welcome!"
# V2 (USE IN-APP SETTINGS INSTEAD)
# Set through UI after logging in
UI_APPNAMENAVBAR still works for navbar branding.
🔐 Session Management Improvements
Impact: LOW - New session features with simple setting updates
What Changed
Session management enhanced with new JWT-based features and improved settings:
| V1 Setting | V2 Setting | Change |
|---|---|---|
jwt.enabled | jwt.persistence | Renamed |
jwt.keyCleanup | jwt.enableKeyCleanup | Renamed |
jwt.secureCookie | (removed) | Always secure now |
| (new) | jwt.enableKeyRotation | New feature |
| (new) | jwt.keyRetentionDays | New feature |
Migration
V1 Configuration:
security:
jwt:
enabled: false
keyCleanup: false
secureCookie: true
V2 Configuration:
security:
jwt:
persistence: true # was 'enabled'
enableKeyCleanup: true # was 'keyCleanup'
enableKeyRotation: true # NEW
keyRetentionDays: 7 # NEW
# secureCookie REMOVED
Environment Variables
V1 (NO LONGER WORKS):
SECURITY_JWT_ENABLED=false
SECURITY_JWT_KEYCLEANUP=false
SECURITY_JWT_SECURECOOKIE=true
V2 (USE THESE):
SECURITY_JWT_PERSISTENCE=true
SECURITY_JWT_ENABLEKEYCLEANUP=true
SECURITY_JWT_ENABLEKEYROTATION=true
SECURITY_JWT_KEYRETENTIONDAYS=7
After Upgrade
Expected behavior: Users will be logged out once after upgrade.
Why: Session token format changed with new JWT implementation.
Action: Users just need to log in again. Normal behavior.
Learn more: Settings Changes - JWT Configuration
🔕 Database Notifications Removed
Impact: LOW - Replaced with better alternative
What Changed
Database backup/import notifications removed.
V1 Configuration (NO LONGER WORKS):
premium:
enterpriseFeatures:
databaseNotifications:
backups:
successful: false
failed: false
imports:
successful: false
failed: false
Why Removed
Replaced with comprehensive audit logging system that provides:
- More detailed information
- Searchable history
- Export capabilities
- Better retention policies
Migration to Audit Logs
V2 Alternative:
-
Enable audit logging:
system:
logging:
level: INFO -
Monitor logs:
docker logs stirling-pdf | grep "Database backup"
docker logs stirling-pdf | grep "Database import" -
Or use audit log UI:
- Log in as admin
- Go to Settings → Audit Logs
- Filter by operation type
- Export as needed
What You Get Instead
Audit logs provide:
- ✅ Database operations (backup, import, export)
- ✅ User actions (login, logout, operations)
- ✅ Admin actions (settings changes, user management)