Commit Graph

56 Commits

Author SHA1 Message Date
stellarshenson
5e563af39b feat: add Activity Monitor admin page with 3-state status and reset functionality
- Add ActivitySample SQLAlchemy model for database persistence
- Add ActivityMonitor singleton with scoring, reset, lifecycle methods
- Add JUPYTERHUB_ACTIVITYMON_INACTIVE_AFTER env var (default 60 min)
- Update defaults: SAMPLE_INTERVAL=600s, RETENTION_DAYS=7
- Fix score calculation to use measured samples only (not theoretical max)
- Add 3-state status: green (active), yellow (inactive), red (offline)
- Add recently_active field in API response
- Add Reset button with confirmation dialog
- Fix green color (explicit #28a745 instead of text-success)
- Add ThreadPoolExecutor for non-blocking Docker stats
- Remove old background sampler code (on-demand sampling now)
- Bump version to 3.7.0
2026-01-20 17:08:23 +01:00
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
7cd56fe2d6 fix: fixed issue with the gpustat not showing in the prompt 2026-01-16 11:38:58 +01:00
stellarshenson
35955c9671 fix: add server_version to global template_vars
HomeHandler doesn't pass server_version to templates (only AdminHandler does).
Added jupyterhub.__version__ to c.JupyterHub.template_vars for global access.
2026-01-14 17:35:18 +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
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
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
f1a8b5e6ce feat: add custom logo support via JUPYTERHUB_CUSTOM_LOGO_URI env var 2026-01-06 21:45:40 +01:00
stellarshenson
43255f70bb fix: store password as bytes, enable COMPOSE_BAKE 2026-01-06 21:25:10 +01:00
stellarshenson
6f85208352 fix: change credentials endpoint from /api/users to /api/admin 2026-01-06 21:00:21 +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
4e4ee47ee9 fix: normalize base URL prefix to avoid double slashes
- Add JUPYTERHUB_BASE_URL_PREFIX that handles root path case
- When BASE_URL is '/', '', or None, prefix becomes empty string
- Prevents //hub/home redirect issue when using root path routing
2026-01-05 13:34:39 +01:00
stellarshenson
14734c0961 fix: use extra_host_config for privileged container mode
DockerSpawner requires extra_host_config['privileged'] = True instead of
spawner.privileged. Bumped version to 3.4.1.
2025-12-12 16:10:02 +01:00
stellarshenson
2674703317 feat: split docker access into docker-sock and docker-privileged groups
- docker-sock: mounts /var/run/docker.sock (container orchestration)
- docker-privileged: runs with --privileged flag (hardware access)

Updated pre_spawn_hook to check both groups and set spawner.volumes
or spawner.privileged accordingly. Documentation updated.
2025-12-12 15:54:47 +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
96f3d546b0 fix: protect jupyterhub_config.py from import errors
Fixed NameError when custom_handlers.py imports from jupyterhub_config.py
by protecting all c.* assignments with 'if c is not None:' checks.

Changes:
- Wrapped c = get_config() in try-except to handle module import context
- Defined DOCKER_SPAWNER_VOLUMES as module-level constant
- Modified get_user_volume_suffixes() to accept volumes dict parameter
- USER_VOLUME_SUFFIXES calculated from constant (importable without c defined)
- Protected all c.* configuration assignments with 'if c is not None:' guards

This allows custom_handlers.py to import USER_VOLUME_SUFFIXES without
triggering "NameError: name 'get_config' is not defined" when the config
file is imported as a module rather than loaded by JupyterHub.

Volume management now works correctly - configuration can be safely imported
by handlers to validate volume names against USER_VOLUME_SUFFIXES.
2025-11-09 22:39:59 +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
e8bf0b7c54 updated 2025-11-04 23:20:46 +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
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
3e52a91924 feat: implement reset home volume and restart server features
- Add custom API handlers for volume reset and server restart
- Create custom home.html template with self-service buttons and modals
- Register handlers in jupyterhub_config.py with @admin_or_self permissions
- Update Dockerfile to copy templates and handlers
- Add custom templates path to JupyterHub configuration
- Update .claude/CLAUDE.md with feature documentation
- Reset Home Volume: DELETE /hub/api/users/{username}/reset-home-volume
- Restart Server: POST /hub/api/users/{username}/restart-server
- Both features use Docker API directly via /var/run/docker.sock
2025-11-03 20:24:20 +01:00
stellarshenson
42b23a547d returned back to CUDA 12.9.1 2025-08-10 21:55:59 +02:00
stellarshenson
254d5670d6 updated to support latest CUDA 13.0 2025-08-10 04:22:21 +02:00
stellarshenson
ba81dd63c2 updated with configurable nvidia autodetect image 2025-08-08 00:52:17 +02:00
stellarshenson
51106cb81b updated with enhanved autodetection routine for nvidia 2025-08-08 00:50:41 +02:00
stellarshenson
1f0def6823 small bugs 2025-08-07 22:43:33 +02:00
stellarshenson
dccd14d6cc updated env variables 2025-08-07 22:42:12 +02:00
stellarshenson
99713fc557 updated to fix the issue with test container 2025-08-07 22:37:05 +02:00
stellarshenson
f5fd86adbf another fix 2025-08-07 22:29:37 +02:00
stellarshenson
293e2af741 fixed the way nvidia autodetection works 2025-08-07 21:52:56 +02:00
stellarshenson
caeb47d0bd updated nvidia detection 2025-08-07 21:40:24 +02:00
stellarshenson
fd3e591aab updated with the fix to the shared volume 2025-08-07 21:05:44 +02:00
stellarshenson
800c259bee updated with the nvidia autodetection 2025-08-07 20:08:36 +02:00
stellarshenson
cb8e6e106f updated permissions 2025-08-07 17:22:30 +02:00
stellarshenson
8d8d874a1c updated names of the enable variables 2025-07-23 23:56:01 +02:00
stellarshenson
d856089b64 small fixes to the documentation of the config files 2025-07-22 09:45:39 +00:00
stellarshenson
c43b622caa reduced default number of mlfow workers 4 -> 1 2025-07-22 00:28:04 +02:00
stellarshenson
7c192782ad fixed GPU configuration 2025-07-18 19:16:06 +02:00
stellarshenson
8c2d2175fc reduced number of volumes used per environment
mlflow was moved to /home/lab/.cache/mlflow and the cache
directory is now a separate volume
2025-07-18 02:51:16 +02:00
stellarshenson
0dfe3bc882 updated 2025-07-18 02:50:24 +02:00