Welcome to the most wonderfully comprehensive and dockerized way to track your subscriptions and recurring costs! This application helps you manage all your recurring payments, from streaming services to software licenses, ensuring you never fall down the rabbit hole of forgotten subscriptions.
- Secure multi-user environment with role-based access control
- Admin Users: Can manage all users, create new accounts, and access admin settings
- Standard Users: Can only manage their own subscriptions and settings
- No public registration - only admins can create new user accounts
- Individual user accounts with personalized settings and isolated data
- Add, edit, and remove subscriptions with ease
- Support for multiple categories: Software, Hardware, Entertainment, Utilities, Cloud Services, News & Media, Education, Fitness, Gaming, and more
- Detailed subscription information including notes
- Daily - Perfect for daily service charges
- Weekly - For weekly subscriptions
- Bi-weekly - Every 2 weeks
- Monthly - The most common billing cycle
- Bi-monthly - Every 2 months
- Quarterly - Every 3 months
- Semi-annually - Every 6 months
- Yearly - Annual subscriptions
- Custom - Define your own billing period (every 5 years? Why not!)
- Get notified before subscriptions expire
- Customizable notification timing (1-365 days before expiry)
- Rich HTML email format with urgency indicators
- Multiple daily checks to ensure timely notifications
- User-specific notification preferences
- Cost tracking with monthly and yearly projections
- Category-based spending breakdown
- Interactive charts and visualizations
- Upcoming renewals dashboard
- Billing cycle distribution analysis
- Per-user preferred display currency (defaults to EUR)
- High-precision Decimal math (no floating point drift)
- Multi-provider live EUR base exchange rates with automatic fallback
- Cached daily (per provider) with manual refresh & force-refetch
- Transparent attempt chain + active provider/mismatch badges in settings & dashboard
- User Settings: Change username, email, and password
- Notification Settings: Configure email preferences, timing, and timezone
- General Settings: Preferred currency, theme, accent color, date format, and exchange rate provider
- Date Format Options: Choose between European (DD/MM/YYYY) or US (MM/DD/YYYY) formatting
- Admin Settings: User management, create/edit/delete users (admin only)
- Smart Sorting: Dashboard defaults to nearest expiry first, with infinite subscriptions always last
- Filters: Filter subscriptions by category, status, and expiration
- Exchange Rate Provider Selection: Choose between multiple free, noβAPIβkey data sources
- Modern, responsive design using Bootstrap 5
- Intuitive navigation and user experience
- Mobile-friendly layout with configurable date formatting (DD/MM/YYYY or MM/DD/YYYY)
- Interactive dashboard with real-time updates and sorting capabilities (defaults to nearest expiry first)
- Status indicators for active/inactive subscriptions
- Easy deployment with Docker
- Pre-built images available on GitHub Container Registry
- Environment variable configuration
version: '3.8'
services:
web:
image: ghcr.io/gittimeraider/subscription-tracker:latest
ports:
- "5000:5000"
environment:
- SECRET_KEY=${SECRET_KEY}
- MAIL_SERVER=${MAIL_SERVER}
- MAIL_PORT=${MAIL_PORT}
- MAIL_USE_TLS=${MAIL_USE_TLS}
- MAIL_USERNAME=${MAIL_USERNAME}
- MAIL_PASSWORD=${MAIL_PASSWORD}
- MAIL_FROM=${MAIL_FROM}
- PUID=${PUID:-1000}
- PGID=${PGID:-1000}
volumes:
- ./data:/app/instance
-
Pull the image from GitHub Container Registry:
docker pull ghcr.io/gittimeraider/subscription-tracker:latest
-
Create environment file:
cp .env.example .env # Edit .env with your configuration
-
Run with docker-compose:
docker-compose up -d
-
Access the application:
- Navigate to
http://localhost:5000
- Default admin credentials:
admin
/changeme
β οΈ Change the default password immediately!- Only admins can create new user accounts
- Navigate to
All of these are optional, though it is advised to use the SECRET_KEY and the MAIL_ environmentals to the very least.
Variable | Description | Default |
---|---|---|
SECRET_KEY |
Flask secret key for sessions | Random string |
DATABASE_URL |
Database connection string | sqlite:///subscriptions.db |
MAIL_SERVER |
SMTP server address | (unset) |
MAIL_PORT |
SMTP server port | 587 |
MAIL_USE_TLS |
Enable TLS for email (true /false ) |
true |
MAIL_USERNAME |
SMTP username | (unset) |
MAIL_PASSWORD |
SMTP password / app password | (unset) |
MAIL_FROM |
From email address | (unset) |
DAYS_BEFORE_EXPIRY |
Default days before expiry to send notification | 7 |
ITEMS_PER_PAGE |
Pagination size for lists | 20 |
CURRENCY_REFRESH_MINUTES |
Freshness window for cached exchange rates (per provider) | 1440 (24h) |
CURRENCY_PROVIDER_PRIORITY |
Comma list controlling provider fallback order | frankfurter,floatrates,erapi_open |
PUID |
Host user ID to run the app process as (for mounted volume ownership) | 1000 |
PGID |
Host group ID to run the app process as | 1000 |
Currently bundled free, noβkey providers (all EUR base):
frankfurter
β https://api.frankfurter.app (ECB sourced, daily; sometimes mid-day updates)floatrates
β https://www.floatrates.com/daily/eur.json (frequent refresh, community mirror)erapi_open
β https://open.er-api.com/v6/latest/EUR (daily with status metadata)
You can set a personal preference in General Settings. The system builds a dynamic priority list putting your choice first, followed by the remaining providers, then falls back to: any cached provider for today β most recent historical cached record β static hardcoded approximations (last resort). A mismatch warning appears if your preferred provider is temporarily unavailable.
Manual Refresh: In General Settings click the βRefresh Ratesβ button (POST /refresh_rates
) to clear todayβs cache and force a live refetch. A debug JSON endpoint is also available at /debug/refresh_rates
(authenticated) to inspect raw values and sample conversions.
Precision: All conversions use Python Decimal
with high precision to avoid cumulative rounding issues when summing many subscriptions.
Attempt Chain Diagnostics: The settings page shows a badge chain like frankfurter:cache β floatrates:fetched
indicating which providers were consulted and how (cache / fetched / failed / fallback-cached / static). This aids troubleshooting provider outages.
Environment Override: You can predefine CURRENCY_PROVIDER_PRIORITY
(e.g. floatrates,frankfurter,erapi_open
) in the container environment; user preference still reshuffles at runtime per session.
To avoid permission issues on the mounted ./data
directory, the image now supports providing a host UID/GID.
Example docker-compose override:
services:
web:
environment:
- PUID=1001
- PGID=1001
Or with plain docker run:
docker run -d \
-e PUID=$(id -u) -e PGID=$(id -g) \
-v $(pwd)/data:/app/instance \
-p 5000:5000 \
ghcr.io/gittimeraider/subscription-tracker:latest
On container start an unprivileged user matching those IDs is created/updated and the process is dropped to it using gosu
.
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587
MAIL_USE_TLS=true
MAIL_USERNAME=[email protected]
MAIL_PASSWORD=your-app-specific-password
MAIL_FROM=[email protected]
MAIL_SERVER=smtp-mail.outlook.com
MAIL_PORT=587
MAIL_USE_TLS=true
MAIL_USERNAME=[email protected]
MAIL_PASSWORD=your-password
MAIL_FROM=[email protected]
- Access the application at
http://localhost:5000
- Login with default admin credentials:
admin
/changeme
β οΈ Immediately change the default password in User Settings- Create user accounts (admin only):
- Go to Settings β Admin Settings β Users
- Click "Add User" to create new accounts
- Set user roles (Admin or Standard User)
Admins can:
- View all users in the system
- Create new user accounts (both admin and standard users)
- Edit user details (username, email, password, role)
- Delete users (with safety restrictions)
- View user statistics
Safety Restrictions:
- Admins cannot delete themselves while logged in
- Cannot delete the last admin user
- Cannot remove admin role from the last admin user
- Deleting a user removes all their subscriptions and settings
- Login to your account
- Navigate to your Dashboard
- Click "Add Subscription"
- Fill in the details:
- Name: Netflix, Spotify, Adobe Creative Suite, etc.
- Company: The service provider
- Category: Choose from predefined categories
- Cost: Amount per billing cycle
- Billing Cycle: Select from available options or use custom
- Start Date: When the subscription began
- End Date: When it expires (leave blank for infinite)
- Notes: Any additional information
- π View: All subscriptions displayed on dashboard with filtering and sorting options
- βοΈ Edit: Click "Edit" to modify subscription details
- π Toggle: Activate/deactivate subscriptions without deleting
- ποΈ Delete: Remove subscriptions with confirmation
- π Filter: By category, status, or expiration timeline
- π Sort: Click column headers or use dropdown to sort by:
- Name (A-Z or Z-A)
- Company (A-Z or Z-A)
- Category (A-Z or Z-A)
- Original Cost (Low to High or High to Low)
- Monthly Cost (Low to High or High to Low)
- Start Date (Oldest to Newest or Newest to Oldest)
- End Date (Earliest to Latest or Latest to Earliest)
- Go to Settings β Notification Settings
- Configure your preferences:
- Enable/disable email notifications
- Set days before expiry for alerts
- Set your timezone
- Test your email configuration:
- Use the "Send Test Email" button to verify your email settings
- Ensure your email address is set in User Settings first
- Check both inbox and spam folder for the test email
- User Settings: Update your username, email, and password
- General Settings:
- Set your preferred display currency
- Choose theme mode (light/dark)
- Select accent color
- Configure exchange rate provider preference
Visit the Analytics page to see:
- Total monthly and yearly costs (converted into your chosen display currency)
- Spending breakdown by category
- Billing cycle distribution
- Upcoming renewals
- Cost projections
Behind the scenes, each subscriptionβs native currency is normalized via EUR base rates, then aggregated. Conversion happens once per request using a cached rates dict for efficiency.
- Set your preferred display currency and provider in General Settings.
- If totals look stale, click Refresh Rates; check attempt chain for failures.
- To test fallback, temporarily set an invalid provider order in
CURRENCY_PROVIDER_PRIORITY
and observe the chain (not recommended in production).
Admin Users:
- Can access all application features
- Manage user accounts (create, edit, delete)
- Access admin settings and user management dashboard
- View system-wide statistics
Standard Users:
- Can manage their own subscriptions and settings
- Access to dashboard, analytics, and personal settings
- Cannot access admin functions or other users' data
- Each user has their own isolated subscriptions and settings
- Users cannot view or modify other users' data
- Analytics and reports are calculated per-user
- Email notifications are sent per-user based on their preferences
On first startup, if no admin users exist, the system creates:
- Username:
admin
- Password:
changeme
β οΈ Change this password immediately after first login!
Admins can manage users through Settings β Admin Settings β Users:
- View all users with their statistics
- Create new users (admin or standard)
- Edit user details and roles
- Delete users (with safety restrictions)
- π¨ Change the default admin password immediately after first login (
admin
/changeme
) - π₯ User Access Control: Only admins can create new user accounts
- π Data Isolation: Users can only access their own subscriptions and settings
- π‘οΈ Admin Protections:
- Admins cannot delete themselves while logged in
- System prevents deletion of the last admin user
- Cannot remove admin privileges from the last admin
- Use strong, unique passwords for all accounts
- Set a secure
SECRET_KEY
in production - Use app-specific passwords for email accounts (especially Gmail)
- Keep your environment variables secure and never commit them to version control
- Regularly review user accounts and remove unused ones
- Use the Test Email feature: Go to Settings β Notification Settings and click "Send Test Email"
- Verify SMTP settings in environment variables
- Check that email credentials are correct
- For Gmail, ensure 2FA is enabled and use app-specific password
- Ensure your email address is set in User Settings
- Check both inbox and spam folder for test emails
- Check application logs for error messages
- Stop the application
- Delete
subscriptions.db
(β οΈ this will delete all data) - Restart the application to recreate the database
- Open General Settings and use the Refresh Rates button.
- Check the attempt chain badges β look for
failed:
entries. - Ensure outbound HTTPS is allowed from the container/host.
- Reduce
CURRENCY_REFRESH_MINUTES
temporarily to force more frequent refetch during testing. - If all live sources fail, the app will log an error and fall back to cached or static rates (may be outdated).
- Monitor system resources if running many subscriptions
- Check email server response times
- Cannot access admin settings: Ensure you're logged in as an admin user
- Cannot create users: Only admin users can create new accounts
- Missing subscriptions: Check you're logged in as the correct user - data is isolated per user
- Default admin account issues:
- If default admin doesn't exist, restart the container to recreate it
- Check logs for user creation messages during startup
- Stop the container
- Delete the database file:
rm ./data/subscriptions.db
- Restart the container (this will recreate the default admin account)
β οΈ Warning: This deletes ALL data including all users and subscriptions
This project is licensed under the MIT License - see the LICENSE file for details.