Commit Graph

66 Commits

Author SHA1 Message Date
stellarshenson
e0ceed8004 feat: add idle culler session extension and harmonize env settings
Session Extension Feature:
- Add JUPYTERHUB_IDLE_CULLER_MAX_EXTENSION env var (default 24h)
- Add SessionInfoHandler and ExtendSessionHandler API endpoints
- Add Session Status card to home page with countdown timer
- Extension tracking in spawner state (resets on server restart)
- Color-coded warnings (yellow <1h, red <30min)

Environment Settings Harmonization:
- Add all ENV defaults to Dockerfile
- Add idle culler settings to compose.yml
- Standardize logo as JUPYTERHUB_LOGO_URI with file:// prefix
- Update NVIDIA_IMAGE to nvidia/cuda:13.0.2-base-ubuntu24.04
2026-01-18 20:28:33 +01:00
stellarshenson
1db8ed1129 feat: rename JUPYTERHUB_SERVICE_GLANCES to JUPYTERHUB_SERVICE_RESOURCES_MONITOR 2026-01-18 18:18:29 +01:00
stellarshenson
940ac7e0d9 feat: add version footer to home page
Display Stellars JupyterHub DS and JupyterHub versions in footer.
Uses short version format (major.minor.patch) only.
2026-01-14 17:30:40 +01:00
stellarshenson
181e2ac5f4 chore: cleanup templates directory structure
- Remove unused *.html from services/jupyterhub/templates/
- Keep only certs/ subdirectory in templates/
- Rename templates_enhanced to html_templates_enhanced
- Update Dockerfile COPY paths
2026-01-14 17:19:12 +01:00
stellarshenson
9e52c3c36a feat: xkcdpass password generation with configurable options
- Move settings_dictionary.yml to services/jupyterhub/conf/
- Replace hardcoded word list with xkcdpass library
- Add JUPYTERHUB_AUTOGENERATED_PASSWORD_WORDS (default: 4)
- Add JUPYTERHUB_AUTOGENERATED_PASSWORD_DELIMITER (default: "-")
- Fix ENABLE_SIGNUP to JUPYTERHUB_SIGNUP_ENABLED in Dockerfile
2026-01-14 17:11:27 +01:00
stellarshenson
d8a306a0d5 feat: externalize settings metadata to YAML dictionary
- Add config/settings_dictionary.yml with category-based structure
- Categories as top-level keys (JupyterHub Core, Docker Spawner, etc.)
- Each setting has name, description, default, optional empty_display
- Update SettingsPageHandler to load from YAML file
- Add pyyaml to Dockerfile pip dependencies
- Refactor pip install to heredoc format with echo message
2026-01-14 16:43:26 +01:00
stellarshenson
022e970dbf feat: standardize env vars with JUPYTERHUB_ prefix, add admin settings page
- Rename 13 environment variables to use JUPYTERHUB_ prefix:
  - ENABLE_GPU_SUPPORT -> JUPYTERHUB_GPU_ENABLED
  - ENABLE_JUPYTERHUB_SSL -> JUPYTERHUB_SSL_ENABLED
  - ENABLE_SERVICE_* -> JUPYTERHUB_SERVICE_*
  - ENABLE_SIGNUP -> JUPYTERHUB_SIGNUP_ENABLED
  - DOCKER_NOTEBOOK_IMAGE -> JUPYTERHUB_NOTEBOOK_IMAGE
  - DOCKER_NETWORK_NAME -> JUPYTERHUB_NETWORK_NAME
  - NVIDIA_AUTODETECT_IMAGE -> JUPYTERHUB_NVIDIA_IMAGE
  - IDLE_CULLER_* -> JUPYTERHUB_IDLE_CULLER_*
- Add SettingsPageHandler with admin-only access at /settings
- Add Settings link to admin navbar
- Sync templates from templates_enhanced to templates
- Update README.md and CLAUDE.md documentation
- No backward compatibility for old variable names
2026-01-14 16:39:34 +01:00
stellarshenson
a40bb19f5b feat: add Notifications link to admin navbar 2026-01-14 16:17:26 +01:00
stellarshenson
4b6ac08ab0 feat: idle server culler for automatic shutdown of inactive servers
- Add jupyterhub-idle-culler package to Dockerfile
- Configure as managed JupyterHub service with role-based scopes
- Environment variables: IDLE_CULLER_ENABLED, IDLE_CULLER_TIMEOUT,
  IDLE_CULLER_CULL_EVERY, IDLE_CULLER_MAX_AGE
- Default: disabled, 24h timeout, 10min check interval
- Bump version to 3.6.0
2026-01-14 16:15:21 +01:00
stellarshenson
cd9c6bf7fa feat: selective notification recipients
Add ability to send notifications to selected servers instead of all.
- New ActiveServersHandler at GET /api/notifications/active-servers
- BroadcastNotificationHandler accepts optional recipients array
- UI with "Send to all" checkbox and server selection list
- Select All/Deselect All buttons, dynamic button text
- Backward compatible - sends to all if recipients not specified
2026-01-14 12:46:49 +01:00
stellarshenson
ad789d7632 fix: lowercase hex encoding for docker volume names 2026-01-08 14:24:06 +01:00
stellarshenson
5e633a9841 fix: encode usernames for docker volume/container names
Use escapism library (same as DockerSpawner) to encode special
characters in usernames when constructing Docker volume and container
names. Fixes volume reset for users with dots in names (e.g., user.name).
2026-01-08 13:37:53 +01:00
stellarshenson
36933afe2b chore: further enhanced display of logo 2026-01-07 03:05:16 +01:00
stellarshenson
a6686ab4a2 feat: custom logo support and authorization handler fix
- Add JUPYTERHUB_LOGO_FILE config for custom logo (served at /hub/logo)
- Fix CustomAuthorizationAreaHandler with @needs_scope decorator
- Import orm inside get() method to fix NameError
- Simplify page.html logo block (always use base_url/logo)
2026-01-07 01:44:54 +01:00
stellarshenson
8be73942da feat: server-side authorization discard button protection
- Add StellarsNativeAuthenticator subclass with CustomAuthorizationAreaHandler
- Pass hub_usernames set to template for Jinja2 conditional logic
- Remove JavaScript API call approach (was clunky with XSRF token handling)
- Fix Bootstrap 5 table hover color override (target td/th explicitly)
2026-01-07 01:16:52 +01:00
stellarshenson
8a420cbb63 feat: document mnemonic passwords and fix table hover styling 2026-01-07 00:44:00 +01:00
stellarshenson
3607c5cb4c fix: use Bootstrap CSS variable for table hover opacity 2026-01-07 00:21:44 +01:00
stellarshenson
20ed13baab fix: reduce spacing before Shutdown Hub button 2026-01-06 23:58:04 +01:00
stellarshenson
6378b68821 fix: admin panel styling and replace eye emoji with icons 2026-01-06 23:55:02 +01:00
stellarshenson
4094e04a67 fix: further admin panel styling refinements
- Reduce user row hover to nearly invisible (0.003 alpha)
- Fix Add Users button: stock colors in light mode, explicit in dark mode
- Make collapse buttons more compact (0.2rem 0.3rem)
- Add username label left padding
- Update journal
2026-01-06 22:54:24 +01:00
stellarshenson
ddc9cb8382 fix: refine admin panel styling - buttons, hover, spacing
- Fix Add Users button to use stock btn-light colors (size only)
- Disable hover on expanded card tables via box-shadow override
- Add padding:0 to expanded user detail td cells
- Make collapse buttons more compact (0.2rem 0.3rem)
- Add left padding to username labels
- Add groups page styling (list items, card footer)
2026-01-06 22:47:22 +01:00
stellarshenson
c1ae9938c1 feat: comprehensive UI styling for notifications, admin panel, tokens
- Add notifications page styling (form, textarea, results table)
- Unify button font sizes to 0.8rem across all pages
- Set collapsed user card padding to 0
- Add subtle hover effect on admin user rows (0.015 alpha)
- Style Add Users form panel with dark mode support
- Style authorization and token pages consistently
2026-01-06 22:26:19 +01:00
stellarshenson
f1a8b5e6ce feat: add custom logo support via JUPYTERHUB_CUSTOM_LOGO_URI env var 2026-01-06 21:45:40 +01:00
stellarshenson
e0f5bf11e3 feat: add compact styling inspired by Stellars Sublime theme 2026-01-06 21:43:41 +01:00
stellarshenson
79a09db50d chore: comment out console logs in admin template 2026-01-06 21:31:46 +01:00
stellarshenson
bd63c72fd4 feat: add per-row copy icon in credentials modal 2026-01-06 21:30:07 +01:00
stellarshenson
bc99236162 fix: move spinner functions before fetch interceptor 2026-01-06 21:18:25 +01:00
stellarshenson
bc76c4f767 feat: add loading spinner during credentials fetch 2026-01-06 21:15:42 +01:00
stellarshenson
f5b8a5717e fix: credentials modal - buttons on top, scrollable list, plain styling 2026-01-06 21:13:19 +01:00
stellarshenson
6f85208352 fix: change credentials endpoint from /api/users to /api/admin 2026-01-06 21:00:21 +01:00
stellarshenson
d5cfbebed5 fix: URL handling in admin fetch interceptor and nav links
- Handle URL objects (not just strings) in fetch interceptor
- Strip query params before checking isUserCreation endpoint
- Remove duplicate 'hub' prefix from authorize/change-password links
2026-01-06 20:52:12 +01:00
stellarshenson
7ee223b193 fix: Dockerfile to copy from templates_enhanced (was reverted) 2026-01-06 20:46:04 +01:00
stellarshenson
6370255746 fix: handle URL objects in fetch interceptor 2026-01-06 20:39:38 +01:00
stellarshenson
139fe144fa feat: admin user creation with auto-generated credentials modal
- Add after_insert event listener to auto-create NativeAuth UserInfo
- Generate memorable 3-word passwords for admin-created users
- Auto-approve users created by admin (is_authorized=1)
- Add after_delete listener to clean up UserInfo on user deletion
- Add GetUserCredentialsHandler API for credential retrieval
- Add password cache (5min expiry) for secure credential handoff
- Enhanced admin.html with credentials modal (copy/download)
- Add templates_enhanced directory with customized templates
- Add NativeAuth nav items (Change Password, Authorize Users)
- Bump version to 3.5.8 (manual)
2026-01-06 20:20:05 +01:00
stellarshenson
d3fe78bb39 fix: sync NativeAuthenticator on admin panel rename
- SQLAlchemy event listener on orm.User.name intercepts ALL renames
- Removed broken SyncedUserAPIHandler (extra_handlers doesn't override)
- Removed RenameUserHandler (redundant with event listener)
- Added version display in browser console (styled badge)
- Build scripts source project.env for VERSION
2026-01-06 17:27:35 +01:00
stellarshenson
79393273ab fix: sync NativeAuthenticator on admin panel rename
- Add SyncedUserAPIHandler extending UserAPIHandler
- Override /api/users/{username} to intercept rename operations
- Sync UserInfo.username after successful JupyterHub rename
- Fixes broken login after admin panel rename
2026-01-06 16:58:35 +01:00
stellarshenson
e001169663 feat: add user rename API and ENABLE_SIGNUP env variable
- RenameUserHandler: PATCH /hub/api/users/{username}/rename
  preserves NativeAuthenticator authorization on rename
- ENABLE_SIGNUP env var controls self-registration (default: 1)
- Updated README, compose.yml, Dockerfile with new config
2026-01-06 16:43:06 +01:00
stellarshenson
acd62e92bf feat: add CERTIFICATE_DOMAIN_NAME env variable for cert generation
- Add CERTIFICATE_DOMAIN_NAME to compose.yml (defaults to localhost)
- Update 00_generate_ssl_cert.sh to use env variable
- Allows custom domain names for self-signed certificates
2026-01-05 15:09:32 +01:00
stellarshenson
dea9e75fbb chore: cleanup startup scripts and bump version to 3.3.2
Removed obsolete 01_nvidia-smi.sh (GPU detection handled in jupyterhub_config.py).
Renamed 02_ensure_groups.py to 01_ensure_groups.py for sequential ordering.
2025-12-04 19:01:11 +01:00
stellarshenson
12953ee4d6 feat: add optional volume descriptions for UI
Added VOLUME_DESCRIPTIONS config dict allowing optional user-friendly
descriptions for volumes shown in management UI.

Changes:
- Added VOLUME_DESCRIPTIONS dict in jupyterhub_config.py (optional, co-defined
  with DOCKER_SPAWNER_VOLUMES)
- Exposed volume_descriptions via c.JupyterHub.template_vars
- Updated home.html to conditionally display descriptions if defined
- If volume not in VOLUME_DESCRIPTIONS, no description shown (UI remains agnostic)

Configuration example:
VOLUME_DESCRIPTIONS = {
    'home': 'User home directory files, configurations',
    'workspace': 'Project files, notebooks, code',
    'cache': 'Temporary files, pip cache, conda cache'
}

Documentation:
- Updated .claude/CLAUDE.md with Manage Volumes implementation details
- Simplified Restart Server section for consistency
- Added template variables to doc/ui-template-customization.md

UI now shows volume name, Docker volume path, and optional description
(if configured). Fully backward compatible - descriptions are optional.
2025-11-09 22:50:13 +01:00
stellarshenson
d03ad7be22 feat: make volume management UI configuration-agnostic
Updated volume management to dynamically read volume names from
DockerSpawner.volumes configuration instead of hardcoding them:

- Added get_user_volume_suffixes() function to extract volume suffixes from
  config matching jupyterlab-{username}_<suffix> pattern
- Exposed USER_VOLUME_SUFFIXES via c.JupyterHub.template_vars for templates
- Updated home.html to use Jinja2 loop generating checkboxes dynamically
  from user_volume_suffixes variable
- Modified ManageVolumesHandler to validate against configured volumes
  instead of hardcoded {'home', 'workspace', 'cache'}
- Removed volume descriptions (e.g., "Contains: User home directory...") to
  keep UI truly agnostic

Now works correctly if volumes are renamed, added, or removed in configuration
without requiring template or handler changes. Volume names displayed exactly
as defined in config (home, workspace, cache by default).
2025-11-09 22:36:22 +01:00
stellarshenson
0e39fac7ac feat: add admin notification broadcast system for active JupyterLab servers
Implemented comprehensive notification broadcast functionality allowing
administrators to send notifications to all active user JupyterLab servers
simultaneously through a dedicated admin panel.

Core Features:
- Admin-only notification panel accessible at /hub/notifications
- Concurrent delivery to all active servers using asyncio with 5s timeout
- Temporary API token generation (5-minute expiry) for authentication
- Support for 6 notification types: default, info, success, warning, error, in-progress
- 140-character message limit with live character counter
- Auto-close toggle and dismiss button in notifications
- Dynamic endpoint URL construction using spawner.server.base_url
- Comprehensive error handling with user-friendly messages
- One-line logging per server with message preview and outcome

Technical Implementation:
- Created BroadcastNotificationHandler in custom_handlers.py
- Created NotificationsPageHandler for admin UI rendering
- Added notifications.html template with Bootstrap 5 form
- Registered handlers in jupyterhub_config.py extra_handlers
- Sends to /jupyterlab-notifications-extension/ingest endpoint
- Payload includes type, message, autoClose, and actions array
- Navigation link added to home.html for admin access

Integration:
- Requires jupyterlab_notifications_extension installed on JupyterLab servers
- Uses correct payload format (type field, not variant)
- Includes Dismiss action button for manual notification closure

Documentation:
- Updated .claude/CLAUDE.md with complete feature documentation
- Updated README.md Features section with notification broadcast details
- Updated .claude/JOURNAL.md with implementation summary
- Removed obsolete FEATURE_PLAN.md

Version: 3.2.0 (bumped from 3.1.2)
2025-11-09 22:05:06 +01:00
stellarshenson
067b613397 feat: add group-based docker.sock access control for privileged users
Implemented built-in protected group system enabling admins to grant trusted users read-write Docker socket access within their JupyterLab containers. Groups are managed through admin panel and cannot be permanently deleted.
2025-11-05 20:15:30 +01:00
stellarshenson
db483de36d feat: build jupyterhub_config.py into Docker image by default
- Change Docker build context from services/jupyterhub to project root
- Copy config/jupyterhub_config.py into image at /srv/jupyterhub/jupyterhub_config.py
- Users can still override with volume mount if needed
- Update all COPY paths in Dockerfile to reflect new build context
- Enables container to work out-of-the-box without external config file

Benefits:
- Image is self-contained and ready to run without dependencies
- Volume mount remains optional for custom configurations
- Default config includes GPU auto-detection and self-service features
2025-11-04 23:25:17 +01:00
stellarshenson
e985786499 fix: add /srv/jupyterhub to Python path for custom_handlers import
- Add /srv/jupyterhub to sys.path before importing custom_handlers
- Separate shell scripts and Python files in Dockerfile COPY commands
- Resolves ModuleNotFoundError for custom_handlers module
- JupyterHub now starts successfully with custom API handlers
2025-11-04 11:06:25 +01:00
stellarshenson
64e2a9d557 fix: pin JupyterHub base image to version 5.4.2
- Replace 'latest' tag with explicit version 5.4.2
- Resolves hadolint DL3007 warning in CI/CD pipeline
- Ensures reproducible builds and prevents unexpected breaking changes
2025-11-04 10:51:04 +01:00
stellarshenson
d9896a7073 feat: add icons to buttons and auto-refresh on stop, implement GitHub Actions CI/CD
UI Enhancements:
- Add Font Awesome icons to all control buttons (stop, start, restart, manage volumes)
- Auto-refresh page after server stop with smooth UI transitions
- Hide/show appropriate buttons based on server state (Restart vs Manage Volumes)
- Re-inject icons removed by JupyterHub's DOM manipulation

Technical Implementation:
- MutationObserver watches for JupyterHub DOM changes after stop
- Immediate UI state correction before page refresh
- Comprehensive console logging for debugging

CI/CD:
- Add GitHub Actions workflow for Dockerfile validation with hadolint
- Triggers on push to main, version tags, and pull requests
- Uses hadolint to ensure Dockerfile best practices
2025-11-04 10:49:32 +01:00
stellarshenson
c06baa8372 docs: add features section and screenshots to README v3.0.14
Documentation enhancements:
- Add comprehensive Features section highlighting key capabilities
- Document GPU auto-detection, user self-service, isolated environments
- Include production-ready features (Traefik, TLS, Watchtower)
- Add Self-Service Volume Management subsection with visual examples
- Include three screenshots demonstrating UI features:
  - Restart Server button (active state)
  - Manage Volumes button (stopped state)
  - Volume selection modal (checkbox interface)
- Position screenshots prominently after feature list
- Provide one-sentence descriptions for each screenshot

Technical updates:
- Increase Stop Server refresh delay to 3 seconds for stability
- Update version to 3.0.14

Screenshots stored in .resources/ directory for future reference
2025-11-04 10:16:45 +01:00
stellarshenson
cd74fc71db feat: evolve user self-service to multi-volume management v3.0.12
Major enhancements to self-service features:
- Transform single volume reset to multi-volume selection (home/workspace/cache)
- Add Font Awesome icons to buttons (fa-rotate, fa-database)
- Fix Bootstrap 5 modal compatibility (data-bs-*, btn-close)
- Fix template inheritance to properly extend default home.html
- Wrap JavaScript in RequireJS callback for proper module loading
- Implement page refresh after Stop/Manage/Restart actions
- Update API endpoint to /api/users/{username}/manage-volumes
- Backend processes multiple volumes with detailed response
- Add Makefile logs target for container log monitoring

Technical fixes:
- Add default JupyterHub templates to template_paths configuration
- Convert modal triggers from Bootstrap 4 to Bootstrap 5 syntax
- Update JavaScript to use Bootstrap 5 Modal getInstance API
- Add json import to custom_handlers.py for request body parsing

Version: 3.0.12_cuda-12.9.1_jh-5.4.2
2025-11-04 10:07:07 +01:00
stellarshenson
bc16b0ca4b debug: add console logging to custom handlers for troubleshooting
- Add console.log statements to track button clicks and API calls
- Log username, base URL, and button existence on page load
- Log success/error responses from API calls
- Help diagnose why restart server button does nothing
2025-11-03 20:44:18 +01:00