Compare commits

..

1715 Commits
0.2.0 ... 0.8.0

Author SHA1 Message Date
Min RK
8892270c24 0.8.0 2017-10-03 21:35:24 +02:00
Min RK
b928df6cba update changelog links for 0.8.0 release 2017-10-03 21:35:24 +02:00
Carol Willing
3fc74bd79e Merge pull request #1462 from minrk/proxy-docs
Document custom proxy implementations
2017-10-03 08:36:02 -07:00
Carol Willing
b34be77fec Merge pull request #1463 from minrk/auth-docs
Document auth_state
2017-10-03 08:29:45 -07:00
Min RK
d991c06098 document auth_state 2017-10-03 13:08:10 +02:00
Min RK
01a67ba156 document custom proxies 2017-10-03 12:42:52 +02:00
Min RK
8831573b6c typos in services.auth headings 2017-10-03 12:42:52 +02:00
Min RK
c5bc5411fb ignore docs/build 2017-10-03 12:42:52 +02:00
Carol Willing
a13ccd7530 Merge pull request #1461 from minrk/apache-docs
Update reverse proxy config examples
2017-10-03 02:46:27 -07:00
Min RK
e9a744e8b7 further clarify config-examples comments
per review
2017-10-03 10:19:43 +02:00
Min RK
582d43c153 add apache reverse proxy to config-examples 2017-10-02 18:18:03 +02:00
Min RK
7b5550928f mention how to generate dhparams
since we use them
2017-10-02 18:17:39 +02:00
Min RK
83920a3258 remove websocket-path-awareness from nginx config
using map, knowledge of the path is no longer necessary
2017-10-02 17:20:09 +02:00
Min RK
d1670aa443 fix mixed tabs and spaces 2017-10-02 16:19:21 +02:00
Min RK
c6f589124e Merge pull request #1458 from ryanlovett/master
Conditionally substitute $http_host for $host.
2017-09-29 16:06:56 +02:00
Carol Willing
35991e5194 Merge pull request #1455 from minrk/db-upgrade-test
Add db-upgrade test
2017-09-28 10:08:27 -07:00
Ryan Lovett
b956190393 Conditionally substitute $http_host for $host.
Necessary when using non-standard port. Closes #1457.
2017-09-28 09:40:51 -07:00
Min RK
122c989b7a specify mysql host and port explicitly
seems to be preferring MYSQL_UNIX_PORT
2017-09-28 18:20:57 +02:00
Min RK
5602575099 move db scripts to general ci directory
- remove shell test-db-upgrade test
- run mysql with docker on Travis because the version there is too old (< 5.7)
2017-09-28 16:20:15 +02:00
Min RK
4534499aad make db scripts accept one db at a time 2017-09-28 16:20:15 +02:00
Min RK
f733a91d7c avoid key length errors with old mysql + jupyterhub 0.7 2017-09-28 16:20:15 +02:00
Min RK
bf3fa30a01 load upgrade_db_url in test 2017-09-28 16:20:15 +02:00
Min RK
2625229847 note about venv 2017-09-28 16:20:15 +02:00
Min RK
2c3eb6d0d6 only count sqlite files when using sqlite 2017-09-28 15:09:17 +02:00
Min RK
5ff98fd1a5 run upgrade-tests on travis via pytest 2017-09-28 15:09:17 +02:00
Carol Willing
f79b71727b Merge pull request #1454 from minrk/auto-login-logout
typo rendering logout page when auto_login=True
2017-09-27 10:33:42 -07:00
Min RK
d3a3b8ca19 test db-upgrade on travis 2017-09-27 19:06:54 +02:00
Min RK
df9e002b9a separate docker-db from init-db
so we don't need docker on Travis
2017-09-27 19:05:55 +02:00
Min RK
a4a2c9d068 add tests for db upgrade with mysql, postgres 2017-09-27 18:41:08 +02:00
Min RK
c453e5ad20 mysql needs an extra step to drop _server_id 2017-09-27 18:34:54 +02:00
Min RK
617b879c2a stamp version before performing upgrade-db 2017-09-27 18:34:54 +02:00
Min RK
a0042e9302 typo rendering logout page when auto_login=True
and include it in test coverage
2017-09-27 14:29:56 +02:00
Min RK
6bbfcdfe4f 0.8.0rc2 2017-09-25 11:20:01 +02:00
Min RK
25662285af Merge pull request #1442 from DeepHorizons/add_more_spawner_statsd
[WIP] Added additional statsd collection for the spawner
2017-09-25 10:43:33 +02:00
Joshua Milas
84d12e8d72 Mock out the statsd object for testing 2017-09-22 12:57:41 -04:00
Joshua Milas
c317cbce36 Added additional statsd info for the spawner
spawner.failure coutner collects the number of failures for various reasons:
spawner.stop timer for seeing how long it takes a user server to stop
2017-09-22 12:13:15 -04:00
Min RK
d279604fac Merge pull request #1439 from minrk/oauth-state-cookie
avoid oauth state cookie collisions
2017-09-22 17:33:27 +02:00
Min RK
70fc4ef886 test concurrent oauth login state 2017-09-21 14:38:10 +02:00
Min RK
24ff91eef5 avoid oauth state cookie collisions
in case of multiple simultaneous

- state arg is strictly required now
- default cookie name in case of no collision is unchanged
- in case of collision, randomize cookie name with a suffix and store cookie_name in state
- expire state cookies after 10 minutes, not 1 day
2017-09-21 14:32:47 +02:00
Min RK
afc6789c74 Merge pull request #1441 from minrk/test-trailing-slash-wtf
debug intermittent failure on Travis
2017-09-21 14:18:08 +02:00
Min RK
819e5e222a stop server before testing trailing-slash handling
ensures `/user/name` is handled by the Hub without relying on CHP bug that was fixed in 3.0
2017-09-21 14:08:08 +02:00
Min RK
e1a4f37bbc cache pip packages on travis 2017-09-21 14:08:08 +02:00
Carol Willing
a73477feed Merge pull request #1435 from Analect/named-server-docs
Adding a short description ref starting/stopping named-servers via API
2017-09-20 21:29:11 -07:00
analect
89722ee2f3 Added in necessity to set c.JupyterHub.allow_named_servers = True 2017-09-20 10:27:28 +01:00
Min RK
30d4b2cef4 0.8.0rc1 2017-09-19 19:07:34 +02:00
analect
ca4fce7ffb Add Analect to contributor list 2017-09-19 16:18:09 +01:00
analect
018b2daace Fixing typo. 2017-09-19 16:17:54 +01:00
analect
fd01165cf6 Adding a short description ref starting/stopping named-servers via API 2017-09-19 14:33:20 +01:00
Carol Willing
34e4719893 Merge pull request #1434 from Analect/rest-api-named-server
Add handling for POST/DELETE of named-servers in hub API introduced in 0.8x
2017-09-19 06:17:05 -07:00
analect
c6ac9e1d15 Add handling for POST/DELETE of named-servers introduced in 0.8x 2017-09-19 13:20:15 +01:00
Min RK
70b8876239 Merge pull request #1413 from yuvipanda/memory-float
Allow non integral memory byte specifications
2017-09-18 10:50:56 +02:00
Min RK
5e34f4481a refer to self.UNIT_SUFFIXES 2017-09-18 10:10:20 +02:00
Min RK
eae5594698 byte specifications always return integers 2017-09-18 10:09:14 +02:00
Carol Willing
f02022a00c Merge pull request #1428 from minrk/default-server-name
allow default (empty) server name with named servers
2017-09-17 20:01:31 -07:00
Min RK
f964013516 exercise default server handler with named servers enabled 2017-09-17 11:55:50 +02:00
Min RK
5f7ffaf1f6 allow default (empty) server name with named servers
remove generated names behavior because it doesn't work
2017-09-17 11:47:17 +02:00
Carol Willing
0e7ccb7520 Merge pull request #1422 from minrk/lowercase-timeouts
lowercase LocalProcessSpawner timeouts
2017-09-15 08:11:15 -07:00
Min RK
c9db504a49 Merge pull request #1424 from phill84/bugfix/control-panel-button-height
wrap control panel button in a span
2017-09-15 06:56:41 -07:00
Jiening Wen
716677393e wrap control panel button in a span
make sure the same style is applied to all buttons in header-container
2017-09-15 15:29:38 +02:00
Min RK
ba8484f161 lowercase LocalProcessSpawner timeouts
traitlets doesn't like uppercase configurables
2017-09-15 12:07:03 +02:00
Yuvi Panda
ceec84dbb4 Merge pull request #1417 from minrk/test-delete
test restoring and deleting spawners while the Hub is down
2017-09-14 12:54:38 -07:00
Yuvi Panda
f2a83ec846 Merge pull request #1418 from minrk/oauth-state-boogaloo
Fixes (and tests!) for oauth state handling
2017-09-14 12:43:39 -07:00
Carol Willing
7deea6083a Merge pull request #1416 from minrk/traitlets-log
avoid error if another traitlets Application is initialized
2017-09-14 10:50:52 -07:00
Min RK
a169ff3548 test oauth redirects
include coverage of state handling
2017-09-14 16:06:57 +02:00
Min RK
f84a88da21 fix oauth state redirect
check for HubOAuth, not HubOAuthenticated
2017-09-14 16:06:36 +02:00
Min RK
eecec7183e fix clearing of oauth state cookie
missing path arg
2017-09-14 16:01:34 +02:00
Min RK
f11705ee26 delete service.server from db when they stop
same ondelete='SET NULL' as on spawner.server
2017-09-14 13:30:38 +02:00
Min RK
78ac5abf23 test restoring and deleting spawners while the Hub is down
- set ONDELETE='set null' on spawner->server relation (fixes error when deleting servers that stopped)
- set `spawner.server = None`, which is not triggered when deleting orm_spawner.server
2017-09-14 13:16:29 +02:00
Min RK
2beeaa0932 avoid error if another traitlets Application is initialized
encountered when doing db debugging in IPython
2017-09-14 11:37:34 +02:00
yuvipanda
90cb8423bc Allow non integral memory byte specifications 2017-09-12 16:19:10 -07:00
Min RK
3b07bd286b Merge pull request #1408 from DeepHorizons/update_service_doc
Updated the reference flask service example to include token auth
2017-09-12 23:49:55 +02:00
Joshua Milas
73564b97ea Updated the whoami-flask example 2017-09-11 12:16:17 -04:00
Joshua Milas
65cad5efad Updated the reference flask example to include token auth 2017-09-11 00:09:57 -04:00
Carol Willing
52eb627cd6 Merge pull request #1407 from willingc/spawn-hooks
Add pre/post spawn hooks to docs
2017-09-08 13:01:56 -07:00
Carol Willing
506e568a9a Add pre/post spawn hooks to docs 2017-09-08 13:00:14 -07:00
Min RK
6c89de082f 0.8.0b5 2017-09-08 11:19:25 +02:00
Carol Willing
6fb31cc613 Merge pull request #1393 from minrk/spawn-future
improve reporting of spawn failure
2017-09-07 10:20:38 -07:00
Carol Willing
cfb22baf05 Merge pull request #1399 from minrk/trailing-slash
add trailing slash on /user/name
2017-09-07 09:59:58 -07:00
Min RK
2d0c1ff0a8 Merge pull request #1404 from minrk/sqla-11
we require sqlalchemy 1.1
2017-09-07 16:48:13 +02:00
Min RK
7789e13879 we require sqlalchemy 1.1
for enum support

[ref](http://docs.sqlalchemy.org/en/latest/changelog/changelog_11.html#change-9d6d98d7acabc8564b8eebb11c28a624)
2017-09-07 15:10:48 +02:00
Yuvi Panda
f7b90e2c09 Merge pull request #1400 from minrk/auth-custom-html
allow Authenticator.custom_html to be HTML
2017-09-06 11:56:14 -07:00
Carol Willing
ccb29167dd Merge pull request #1392 from minrk/rm-extra-log
update docs to preferred method of writing to log file
2017-09-06 07:32:25 -07:00
Min RK
4ef1eca3c9 allow Authenticator.custom_html to be HTML 2017-09-06 15:14:26 +02:00
Min RK
c26ede30b9 Point users to /hub/home to retry spawn on spawn failure 2017-09-06 15:03:26 +02:00
Min RK
64c69a3164 update docs to preferred method of writing to log file
extra_log_files config is unreliable and doesn't capture all output.

Piping output is much more robust and reliable.
2017-09-06 14:38:33 +02:00
Min RK
ad7867ff11 add trailing slash on /user/name
proxies may not route `/user/name` correctly, only `/user/name/...`, so make sure that `/user/name` is redirected to `/user/name/`

this manifests as a redirect loop between /user/name and /hub/user/name when a route exists but /user/name is still
being routed to the Hub
2017-09-06 12:37:22 +02:00
Yuvi Panda
14fc1588f8 Merge pull request #1380 from minrk/cull-idle-users
add —cull-users to cull_idle_servers
2017-09-05 12:48:24 -07:00
Min RK
7e5a925f4f raise original spawn failure on implicit spawn
so the error message is the same, however it was arrived at.

potential downside: it could look like the current request is spawning and failing,
rather than the reality that a previous spawn failed and we are just re-presenting the earlier error.
It's possible for there to have been a long time in between spawn and error.
2017-09-04 14:27:01 +02:00
Min RK
3c61e422da prevent implicit spawn on /user/:name if previous spawn failed
require users to visit /hub/home and click 'Start My Server' to get a new server

Visits to /hub/user/:name will get an error if the previous spawn failed,
rather than triggering a new spawn.
This should guarantee that a user sees an error if their spawn failed,
regardless of when the failure occurred and how long it took.
Some cases of slow errors could result in triggering a new spawn indefinitely without
the user seeing an error message.

/hub/spawn was a simple redirect to /user/:name in the absence of a spawn form,
but now clears the `_spawn_future` prior to redirect
to signal that a new spawn has been explicitly requested in the case of a prior failure.
2017-09-04 14:17:24 +02:00
Min RK
0e2cf37981 point to single-user logs when spawner fails to start 2017-09-04 13:14:07 +02:00
Min RK
503d5e389f render pending page if triggered spawn doesn't finish
instead of redirecting, which starts redirect loop counter
2017-09-04 12:02:40 +02:00
Min RK
7b1e61ab2c allow waiting for pending spawn via spawner._spawn_future
avoids losing errors when visiting `/hub/user/:name` during a pending spawn
2017-09-04 11:53:42 +02:00
Min RK
4692d6638d 0.8.0b4 2017-08-31 16:47:12 +02:00
Carol Willing
7829070e1c Merge pull request #1383 from minrk/singleuser-token-cookie
set cookie on singleuser when authenticated with ?token=...
2017-08-31 09:31:35 -05:00
Min RK
5e4b935322 only HubOAuth can set token cookie 2017-08-31 16:04:54 +02:00
Carol Willing
4c445c7a88 Add jencabral to contributors 2017-08-31 07:52:08 -05:00
Carol Willing
8e2965df6a Merge pull request #1384 from minrk/spawner-db
restore db access on Spawner
2017-08-31 07:50:18 -05:00
Min RK
7a41d24606 set cookie on singleuser when authenticated with ?token=...
Allows `/user/name?token=...` URL to login users for more than one request.

matches token behavior of regular notebook server.
2017-08-31 13:53:48 +02:00
Min RK
5f84a006dc restore db access on Spawner
Shouldn’t be strictly necessary, but doesn’t hurt
2017-08-31 10:03:44 +02:00
Carol Willing
e19296a230 Merge pull request #1382 from minrk/request-token
let admins request tokens for other users
2017-08-31 00:04:59 -04:00
Min RK
89ba97f413 exercise more token API cases
separate parametrize cases for clarity
2017-08-30 14:38:00 +02:00
Min RK
fe2157130b Merge pull request #1381 from minrk/log-fix
fix logging error when login_user is called with no form data and login fails
2017-08-30 14:09:52 +02:00
Min RK
e3b17e8176 Merge pull request #1379 from ding-c3/master
Pass timeout value to exponential_backoff in wait functions
2017-08-30 14:05:42 +02:00
Min RK
027f2f95c6 let admins request tokens for other users 2017-08-30 12:31:41 +02:00
Min RK
210975324a fix logging error when login_user is called with no form data and login fails 2017-08-30 11:31:44 +02:00
Min RK
f9a90d2494 add —cull-users to cull_idle_servers
allows deleting idle users in addition to servers for temp-user cases such as binder/tmpnb
2017-08-30 10:31:44 +02:00
Alex Ding
932689f2f8 Pass timeout value to exponential_backoff in wait functions 2017-08-29 17:45:21 -07:00
Min RK
f91e911d1a Merge pull request #1375 from lsst-sqre/master
Prevent "extra" from being used before definition.
2017-08-29 08:36:25 -04:00
Adam Thornton
b75cce857e Merge pull request #1 from lsst-sqre/ticket/DM-11663
Fix "extra" so it isn't used before definition.
2017-08-28 19:00:17 -04:00
adam
62f00690f7 Fix "extra" so it isn't used before definition. 2017-08-28 15:58:31 -07:00
Yuvi Panda
f700ba4154 Merge pull request #1368 from minrk/check-version-error
Provide more detailed error message in case of version mismatch
2017-08-28 13:27:00 -04:00
Min RK
8b91842eae Merge pull request #1369 from minrk/template-typo
typo in navbar template
2017-08-27 16:41:44 -04:00
Min RK
80a9eb93f4 Merge pull request #1370 from yuvipanda/button-roles
Add role=button attribute to all <a> & <span> buttons
2017-08-27 15:39:04 -04:00
yuvipanda
e1deecbbfb Add role=button attribute to all <a> & <span> buttons
Simple accessibility win - screen readers will now be
able to properly present these as buttons than links.
2017-08-27 11:17:22 -04:00
Min RK
d3142704b7 typo in navbar template
mixed up elements causing funky alignment on some pages
2017-08-26 22:42:17 -04:00
Min RK
447edd081a Provide more detailed error message in case of version mismatch
this is the most likely cause of redirect loops when using docker,
so record the spawner version and check it when a redirect is detected.

In the event of a redirect and mismatch, fail with a message explaining the version mismatch and how to fix it.
2017-08-26 22:41:24 -04:00
Min RK
e1531ec277 Merge pull request #1366 from minrk/typo
typo in proxy recovery
2017-08-26 20:21:51 -04:00
Min RK
d12ac4b1f6 typo in proxy recovery
should have been the dict of instantiated services, not the list of service configurations
2017-08-26 15:25:17 -04:00
Min RK
17851b7586 0.8.0b3 2017-08-26 13:51:12 -04:00
Min RK
118e2fa610 Merge pull request #1364 from minrk/test-start-stop-race
exercise start/stop race conditions
2017-08-26 13:37:41 -04:00
Min RK
8e3553462c exercise start/stop race conditions
this doesn’t cover all the edge cases of each possible stage for the races, but it gets the basics covered.
2017-08-26 11:57:05 -04:00
Carol Willing
37da47d811 Merge pull request #1356 from minrk/proxy-race
rework spawn futures to fix races
2017-08-26 11:07:55 -04:00
Min RK
a640a468fb Merge pull request #1362 from stuartcampbell/master
Improve help comments for SSL key/certs configuration parameters
2017-08-26 09:41:47 -04:00
Min RK
92f034766e Merge pull request #1355 from minrk/update-oauth-secret
update oauth secret if API tokens change
2017-08-26 09:41:14 -04:00
Min RK
f7ea451df8 get the tests running 2017-08-25 18:12:15 -04:00
Stuart Campbell
1b7f54b462 Make SSL cert/key help clearer. 2017-08-25 14:52:23 -04:00
Stuart Campbell
b14b12231a Correct typo to have consistent comments 2017-08-24 16:53:25 -04:00
Min RK
2866be9462 don’t allow start while stop is pending
- start fails with 400 if stop is pending
- set spawn_pending across a whole spawn (including proxy)
- proxy_pending is only around the proxy
2017-08-23 23:35:19 -04:00
Min RK
f8648644bf ensure _stop_pending is always True on stop_single_user
previously there was a race during `delete_route`

apply the same logic as _start_pending
2017-08-23 18:30:49 -04:00
Min RK
69d4d48db0 rework spawn futures to fix races
1. set _proxy_pending before first wait to ensure that there is never a gap between setting spawn flags
2. always call `finish_user_spawn` to reduce the number of finalization cases
3. wait for proxy to finish on the slow_spawn timeout, not just start, because we are only interested in the total duration for page responsiveness
2017-08-21 11:27:30 +02:00
Min RK
df309749f2 update oauth secret if API tokens change
handle will_resume case correctly, where an API token *may* be re-used.

Previously, we only did it right if the token was *always* reused,
but clearing out a container would get it into a bad state.
2017-08-21 11:23:17 +02:00
Min RK
58751067db Merge pull request #1354 from minrk/log-typo
typo: use app_log, not self.log
2017-08-20 15:49:56 +02:00
Min RK
4fd70cf79b app_log typo 2017-08-20 15:48:55 +02:00
Carol Willing
ff15bad375 Merge pull request #1353 from minrk/log-connection-error
log error when failing to connect to Hub
2017-08-20 10:45:32 +02:00
Min RK
90ac4ab6fe 0.8.0b2 2017-08-20 10:11:45 +02:00
Min RK
cba5bb1676 log error when failing to connect to Hub
for better diagnosis
2017-08-20 10:03:52 +02:00
Min RK
4b5fa404fc Merge pull request #1352 from minrk/singleuser-image
build jupyterhub/singleuser on this repo
2017-08-20 09:45:54 +02:00
Min RK
c4ac1240ac Merge pull request #1347 from minrk/re-use-token
handle and test a few unlikely cases when Spawners reuse tokens
2017-08-20 09:45:35 +02:00
Min RK
d384ad2700 ensure notebook is installed 2017-08-18 17:57:53 +02:00
Min RK
c3da0b8073 include singleuser in sdists 2017-08-18 17:55:00 +02:00
Min RK
9919cba375 add BASE_IMAGE as a build arg 2017-08-18 17:45:35 +02:00
Min RK
1e6b94de92 add singleuser build dir from dockerspawner 2017-08-18 17:36:08 +02:00
Min RK
8451a4cd08 clarify and simplify api token tests 2017-08-18 13:09:41 +02:00
Carol Willing
48f1da1b8d Merge pull request #1348 from minrk/oauth-state
use state field for internal OAuth
2017-08-17 19:22:11 +02:00
Carol Willing
e20050b719 Merge pull request #1346 from minrk/test-admin-sort
Fix (and test!) sorting of admin page
2017-08-17 19:12:37 +02:00
Min RK
a9c0a46a06 add missing classes to services.auth 2017-08-17 17:29:45 +02:00
Min RK
03bb094b90 update service-whoami examples to include OAuth 2017-08-17 17:29:45 +02:00
Min RK
5d0d552c26 fix check for service startup 2017-08-17 17:29:45 +02:00
Min RK
2d50cef098 implement state handling in HubOAuth 2017-08-17 17:29:45 +02:00
Min RK
d6d0b83b4e remove redundant oauth callback implementation in singleuser 2017-08-17 17:29:45 +02:00
Min RK
f1dbeda451 regenerate cookie_secret on every single-user spawn
ensures that singleuser cookies do not persist across single-user instances

relaunching a singleuser instance invalidates all cookies used with that instance
2017-08-17 17:29:45 +02:00
Min RK
512bbae5cb handle and test a few unlikely cases when Spawners reuse tokens
- test that .will_resume preserves tokens (worked, but wasn't tested)

If a Spawner reuses a token, validate it in the db:

- verify that it's in the db
- if it doesn't map onto the right user, revoke the token
- if it's not in the db, insert it as a user-provided token

The most likely case is prior unclean shutdown of something like DockerSpawner,
where a spawn failed and thus the token was revoked,
but the container was in fact created.
2017-08-17 17:29:33 +02:00
Min RK
8c575d40af fix sort-by-running on admin page
server_id is on Spawner, not User anymore
2017-08-17 17:29:19 +02:00
Min RK
d6b9909bc6 test admin page sort order
just exercise the handler, sort results are not verified
2017-08-17 17:29:19 +02:00
Min RK
ef7d6dc091 Merge pull request #1350 from minrk/allow-fail-nightly
allow failures on python: nightly
2017-08-17 17:27:54 +02:00
Min RK
57f707bbfd allow failures on python: nightly
since they break stuff sometimes.
2017-08-17 17:27:07 +02:00
Min RK
0ae7213366 Merge pull request #1344 from minrk/0.8-changes
Start drafting 0.8 changelog
2017-08-17 17:24:05 +02:00
Min RK
22ff7aa672 begin 0.8 changelog
most of the changes I could find!
2017-08-17 17:21:48 +02:00
Carol Willing
ca579fbf4a Merge pull request #1342 from willingc/toc-tweak
Add detail to tutorials toc section
2017-08-16 15:52:22 +02:00
Carol Willing
f2eb30d090 Add detail to tutorials toc section 2017-08-16 15:41:22 +02:00
Min RK
63a4b4744b Merge pull request #1335 from willingc/upgrade-08
Add upgrade to 0.8 doc
2017-08-15 18:09:12 +02:00
Min RK
e03b5b3992 Merge pull request #1340 from zonca/patch-2
Fix broken jupyterhub getting started link
2017-08-15 18:08:56 +02:00
Min RK
fa4a27fb1a 0.8.0b1 2017-08-15 18:06:58 +02:00
Andrea Zonca
d3a6aa2471 Fix broken jupyterhub getting started link 2017-08-14 16:02:40 -05:00
Carol Willing
8bd64cff59 Merge pull request #1338 from willingc/update-conrtib
Update contributor list [ci skip]
2017-08-13 16:31:50 -07:00
Carol Willing
760db17640 Update contributor list 2017-08-13 16:26:33 -07:00
Carol Willing
a9cb25f3a2 Update gallery-jhub-deployments.md 2017-08-12 08:07:47 -07:00
Min RK
d9d5ddb77e Merge pull request #1337 from yuvipanda/urlencoding
Fix bug causing failures with special chars in user names
2017-08-12 15:28:40 +02:00
yuvipanda
9b8e5b03b4 Fix bug causing failures with special chars in user names
Fixes #1336
2017-08-11 16:46:19 -07:00
Yuvi Panda
02f0c4a5b8 Merge pull request #1333 from minrk/client-id
use fully-escaped name in oauth_client_id
2017-08-11 12:30:55 -07:00
Carol Willing
b254716cee Add upgrade to 0.8 doc 2017-08-11 09:05:54 -07:00
Min RK
4c52ad6f7c Merge pull request #1331 from willingc/travis-req
verify requirements installed in travis builds
2017-08-11 16:34:13 +02:00
Min RK
0c09bfcafa use fully-escaped name in oauth_client_id
because it will be a cookie key
and @ is not legal there
2017-08-11 16:32:54 +02:00
Carol Willing
0b67546481 Allow sqlalchemy to float upward 2017-08-11 06:08:52 -07:00
Min RK
2698b00fb9 Merge pull request #1330 from willingc/restructure-doc
Restructure doc source folders
2017-08-11 14:11:36 +02:00
Carol Willing
f7ce705999 Merge pull request #1332 from pjamason/patch-1
Update gallery-jhub-deployments.md
2017-08-10 16:23:11 -07:00
pjamason
ee14131827 Update gallery-jhub-deployments.md
added jupyterhub.ucsd.edu
2017-08-10 13:07:27 -07:00
Carol Willing
828c499ac7 Add missing images 2017-08-10 10:39:44 -07:00
Carol Willing
a43d594452 correct link 2017-08-10 09:53:29 -07:00
Carol Willing
406d572a7b keep sqlalchemy version from floating upward 2017-08-10 09:48:49 -07:00
Carol Willing
71c38fd515 modify link from md to rst 2017-08-10 09:07:38 -07:00
Carol Willing
68e02dd62a Correct links 2017-08-10 09:07:38 -07:00
Carol Willing
dd1902b1d9 update image links 2017-08-10 09:00:04 -07:00
Carol Willing
39041ee08c Update toc 2017-08-10 09:00:04 -07:00
Carol Willing
eb6a2f9e89 Restructure doc folder structure 2017-08-10 09:00:04 -07:00
Min RK
4f826d8245 Merge pull request #1325 from willingc/services-update
Update services getting started docs
2017-08-10 12:18:13 +02:00
Min RK
a434a6f144 Merge pull request #1328 from willingc/test-travis
Update pin on sqlalchemy for travis
2017-08-10 12:15:50 +02:00
Carol Willing
0fe1020022 Update pin on sqlalchemy for travis 2017-08-09 11:46:55 -07:00
Carol Willing
8aca08f508 Edit REST doc per minrk 2017-08-09 10:38:17 -07:00
Carol Willing
fb0331aa4c Edits per minrk 2017-08-09 10:28:38 -07:00
Carol Willing
184a9bceb9 Add link to HTCondor and JupyterHub 2017-08-09 10:17:31 -07:00
Min RK
dfef7c2b52 Merge pull request #1321 from willingc/doc-services
Add autodoc of services and update services.auth for OAuth
2017-08-09 11:37:16 +02:00
Min RK
6b16b51064 Merge pull request #1326 from willingc/aws-workshop
Add CTB's tutorial config on AWS to gallery of deployments
2017-08-09 08:33:06 +02:00
Carol Willing
85a75b637a Add automodule for app 2017-08-08 23:07:28 -07:00
Carol Willing
fae2d9414a Remove heading in docstring 2017-08-08 23:06:50 -07:00
Carol Willing
61e263b160 Correct docstring that was preventing build 2017-08-08 23:05:20 -07:00
Carol Willing
ac13140083 Edit some classes 2017-08-08 23:02:12 -07:00
Carol Willing
024fd07ec8 Update autodoc doc files 2017-08-08 23:01:08 -07:00
Carol Willing
95175155d4 Update autodoc of services.auth and add services 2017-08-08 22:51:35 -07:00
Carol Willing
e5c088f8d6 add alembic to conda env 2017-08-08 22:41:42 -07:00
Carol Willing
42a103c76f bump bootprint versions 2017-08-08 22:41:23 -07:00
Carol Willing
b70f2fa20a remove schema error 2017-08-08 22:41:08 -07:00
Carol Willing
8e69b158eb Update rest doc 2017-08-08 21:03:20 -07:00
Carol Willing
6e2c544a19 correct link formatting 2017-08-08 20:59:06 -07:00
Carol Willing
c62d080e9c Add CTB's tutorial config on AWS 2017-08-08 17:48:20 -07:00
Carol Willing
bd0e00ed86 Add tokens can be for activities not tied to a specific user 2017-08-08 16:01:41 -07:00
Carol Willing
264a78e2cc Add note about single-user servers auth and tokens 2017-08-08 15:46:47 -07:00
Carol Willing
4f95ef437f Add more complex requests example for API 2017-08-08 15:37:35 -07:00
Carol Willing
f0556954ed Deprecate and de-emphasize 'jupyterhub token' 2017-08-08 15:25:41 -07:00
Carol Willing
44bc569868 Update services getting started docs 2017-08-08 15:13:30 -07:00
Carol Willing
1e9bbb1d14 Merge pull request #1323 from minrk/prefix-slash
handle missing trailing slash on /hub
2017-08-08 09:07:56 -07:00
Min RK
f2953f6b09 handle missing trailing slash on /hub 2017-08-08 14:23:07 +02:00
Min RK
fa4c5ec9d4 Merge pull request #1320 from minrk/access-link
make sure we send users to `/user/name/`, not just `/user/name`
2017-08-08 13:35:45 +02:00
Min RK
546268809f add / to user-redirect
Some proxies may not correctly route /user/name, only /user/name/...
2017-08-08 12:02:36 +02:00
Min RK
6af4c0f9e0 Merge pull request #1322 from willingc/link-update
Correct broken links in docs
2017-08-08 09:50:33 +02:00
Min RK
7d0fd85d65 Merge pull request #1319 from minrk/test-mysql
Test against postgres, mysql (again)
2017-08-08 09:50:12 +02:00
Carol Willing
15b78307fb Correct broken links in docs 2017-08-07 14:35:17 -07:00
Min RK
6ba3090cd5 add trailing slash to user access link 2017-08-07 15:18:20 +02:00
Min RK
74c4c58e37 ensure mysql has proper unicode on travis 2017-08-07 13:18:28 +02:00
Min RK
31f63264b0 ensure oauth uses same db session as app
further remnant of test threads
2017-08-07 13:18:28 +02:00
Min RK
9e7dbbbbff avoid recreating existing users in test_proxy
db tests re-use users across sessions
2017-08-07 13:18:28 +02:00
Min RK
c1d120c9bb cleanup named servers 2017-08-07 13:18:27 +02:00
Min RK
3955a8c1d0 limit unique columns to 255 chars
for MySQL key size limits (767 = 256 * 3 - 1 for utf8)
2017-08-07 13:18:27 +02:00
Min RK
12f8073e5d only create first user if it doesn't exist 2017-08-07 13:18:27 +02:00
Min RK
ec2b1dd39b install mysql/postres drivers on Travis 2017-08-07 11:23:34 +02:00
Min RK
e9d603abf1 run tests with mysql, postgres
make sure everything works
2017-08-07 11:23:34 +02:00
Carol Willing
ac33ba6ff4 Merge pull request #1316 from minrk/rm-scoped-session
drop scoped_session
2017-08-06 09:01:50 -07:00
Carol Willing
3b4888b8ba Merge pull request #1314 from minrk/spawner.start-doc
update spawner.start docs
2017-08-06 08:58:49 -07:00
Carol Willing
5c64c88d5a Merge pull request #1312 from minrk/reverse-generated-token
reverse generated-tokens default logic
2017-08-06 08:57:27 -07:00
Carol Willing
924d095c68 Merge pull request #1311 from minrk/oauth-token-no-service
handle OAuthAccessTokens with no user
2017-08-06 08:49:37 -07:00
Min RK
700ccb17cb Merge pull request #1317 from minrk/proxy-check-routes
disable periodic check_routes during proxy tests
2017-08-06 15:06:36 +02:00
Min RK
1d156f8183 disable periodic check_routes during proxy tests
can race tests and create inconsistent state
2017-08-06 14:39:42 +02:00
Min RK
c0e2c5cb71 drop scoped_session
this was an artifact of the now-removed test thread
2017-08-06 14:29:10 +02:00
Min RK
25d19732e0 keep salting generated tokens
all the savings are in rounds, but keep salt because it still prevents the ability to hash a token once and check it against the whole db
2017-08-06 14:16:47 +02:00
Min RK
f0b8d56e9f fix oauth hashed column sizes 2017-08-06 13:28:06 +02:00
Min RK
718a3fe7ef update spawner.start docs
remove mention of self.user.server, which is deprecated in 0.7
2017-08-06 13:15:46 +02:00
Carol Willing
ca6e0ec9b9 Merge pull request #1307 from minrk/last_activity
remove last_activity from server
2017-08-05 15:34:45 -07:00
Min RK
a27765f7d5 reverse generated-tokens default logic
user-provided tokens are added in exactly one place,
so switch default handling of tokens to generated=True
and explicitly distrust user tokens.

Add JupyterHub.trust_user_provided_tokens flag so that users can avoid the extra hashing
if they know they are providing good keys.
2017-08-05 15:36:03 +02:00
Min RK
bf1dd03df3 handle OAuthAccessTokens with no user
This shouldn’t happen, raise if it does.

If a token API request is authenticated with no user or service, delete the token because it is invalid and return with 404 because it doesn’t correspond to an existing user.
2017-08-05 15:01:22 +02:00
Min RK
2726648982 typo in OAuthAccessToken.service
Token.session doesn’t exist

OAuthAccessTokens are never associated with services
2017-08-05 14:58:41 +02:00
Min RK
275a4ce18d remove last_activity from server
and put it on individual spawners
2017-08-05 14:55:09 +02:00
Carol Willing
0b34e13dd4 Merge pull request #1303 from minrk/message-202
consolidate server APIHandlers
2017-08-04 07:43:40 -07:00
Carol Willing
e666261434 Merge pull request #1308 from minrk/rest-api-finish
finish up oauth swagger doc
2017-08-04 07:40:06 -07:00
Min RK
57c8ad6b92 consolidate server APIHandlers
no need for separate handlers for named and default servers

avoid claiming that empty responses are JSON.
2017-08-04 16:17:20 +02:00
Min RK
3f032abc25 finish oauth swagger doc
- clarify that /authorize is not really an API endpoint, but the redirect target
- /oauth2/token accepts x-www-form-urlencoded not json
2017-08-04 15:23:50 +02:00
Carol Willing
f86202c07d Update link to Jupyter contributor guide 2017-08-04 04:02:18 -07:00
Min RK
1b0ff0a5f6 Merge pull request #1093 from willingc/oauth-doc
Add docs for OAuth
2017-08-04 12:14:01 +02:00
Carol Willing
cebb962645 Edit per mirnk review 2017-08-03 10:34:12 -07:00
Min RK
55000f98bc include non-empty body with 202 responses
reply claims to be application/json, so make sure it has some content
2017-08-03 12:01:19 +02:00
Min RK
449aff1b1d Merge pull request #1302 from minrk/properties
restore user.running property
2017-08-03 12:00:52 +02:00
Min RK
3c591f744b Merge pull request #1305 from minrk/alembic-log
hook up alembic logging to Hub app if it's running
2017-08-03 11:46:32 +02:00
Min RK
329781023f use futures to avoid races on slow spawners
trigger events by hand so that performance can't cause races
2017-08-03 11:45:29 +02:00
Min RK
8d9731e241 hook up alembic logging to Hub app if it's running
avoids calling `logging.fileConfig` which disables all exiting logging when called
2017-08-03 11:28:53 +02:00
Min RK
bde37ba9c2 Merge pull request #1299 from minrk/hash-auto
only apply reduced hash+salt to internally generated tokens
2017-08-03 11:13:25 +02:00
Min RK
088fdc8f42 Deprecate User.spawn|stop_pending flags
Rather than removing them immediately
2017-08-03 11:12:10 +02:00
Min RK
886005be2a handle named servers in user_stopped callback 2017-08-03 11:09:28 +02:00
Min RK
684afed3f1 restore user.running property
it was made a method for handing named_servers,
but that made things way more complicated and replaced a boolean flag with a callable,
which would behave unexpectedly but without error if a boolean flag was expected.

Spawners have properties for dealing with this now, so use spawners

Restore `user.running` as an alias for `user.spawner.ready`
2017-08-03 11:09:27 +02:00
Min RK
210d7e59fd Merge pull request #1301 from minrk/total-running-limit
add active_server_limit
2017-08-03 11:08:23 +02:00
Min RK
a19a94b2c2 test active_server_limit 2017-08-03 10:52:32 +02:00
Min RK
9bf70208c8 return 'spawn' pending for spawn or proxy_pending
In general, we treat both the same way
2017-08-03 10:52:01 +02:00
Min RK
fada0d99f0 call it active_server_limit 2017-08-03 10:50:50 +02:00
Min RK
e6ce468301 set Spawner.server directly
avoids Spawner.server property looking up on the ORM every time,
which is expensive and we want to check `Spawner.server is None` often.
2017-08-03 09:59:01 +02:00
Min RK
875e5d59fe Merge pull request #1300 from minrk/check-hub-ip
verify route targets in check_routes
2017-08-02 22:28:38 +02:00
Min RK
6556135a69 verify route targets in check_routes
updates routes that have the wrong target
2017-08-02 11:23:49 +02:00
Min RK
8636b4ebca Merge pull request #1294 from minrk/alembic-tag
always include and check alembic revision
2017-08-02 11:14:44 +02:00
Min RK
4a5f914a62 only apply reduced hash+salt to internally generated tokens
don't trust any user-provided tokens to have decent entropy, regardless of size
2017-08-02 11:14:18 +02:00
Yuvi Panda
47b6014d13 Merge pull request #1297 from minrk/check-enabled-auth-state
prevent saving auth_state if auth_state is not enabled.
2017-08-01 09:24:34 -07:00
Yuvi Panda
1995d825df Merge pull request #1293 from minrk/test-spawn-limit
test pending spawn count
2017-08-01 09:23:36 -07:00
Min RK
f49606dff6 add user.count_active_users
produces summary of active/pending/ready spawner counts

Avoids brittle bookkeeping of running counts,
computing the value upon request.

For 10k users this is still only a few milliseconds, which seems worth it
2017-08-01 17:00:45 +02:00
Min RK
7520d4b81e add concurrent_user_limit
limits total active users, not just spawns
2017-08-01 16:22:54 +02:00
Min RK
083408a685 add pending/ready/active properties to Spawner
- pending: stop or start is pending
- ready: spawner is running and ready (not pending)
- active: spawner is running or pending (consuming resources)
2017-08-01 16:17:37 +02:00
Min RK
9c4972239d prevent saving auth_state if auth_state is not enabled.
allows Authenticators to return auth_state without having to check enable_auth_state
2017-08-01 10:51:44 +02:00
Min RK
4458f2e6d4 error when db mismatches is SystemExit now
since we catch explicitly and call `self.exit` with a nice message
2017-07-31 17:04:27 +02:00
Min RK
a24027f188 hook up app logging in upgrade-db
matches default formatting
2017-07-31 16:19:47 +02:00
Min RK
c749fc05f4 update 0.8 alembic revision
add some missing transactions
2017-07-31 16:19:24 +02:00
Min RK
5ad77df04f check database revision on launch
fail with informative error if version mismatches

Since we weren't always tagging before,
we have to handle no tag being present:

- database empty (use latest because we are about to create everything anew)
- if 'spawners' is present, assume 0.8.dev
- if 'services' is present, assume 0.7.x
- else: assume base revision when we started tracking this stuff
2017-07-31 16:18:58 +02:00
Min RK
4b51d67d35 match alembic log formatting to default hub log format 2017-07-31 15:12:39 +02:00
Min RK
88268bd76f test spawn_pending_count
make sure to cover various cases of spawn failure
so that failed spawns don't leak pending-spawn counts
2017-07-31 12:39:06 +02:00
Min RK
744d96330e use properties for spawn_pending 2017-07-31 11:45:01 +02:00
Min RK
55c3164a7d Make default concurrent spawn limit 100
it's a conservative default, and deployments can turn it up if need be
2017-07-31 11:24:21 +02:00
Min RK
c78e31b136 Merge pull request #1290 from yuvipanda/concurrent_spawn_limit
Add support for limiting the number of concurrent spawns
2017-07-31 10:28:37 +02:00
Min RK
ecfd0a6796 Merge pull request #1285 from Carreau/spawner-import
Try enforcing methods overwrite at import time.
2017-07-31 10:27:28 +02:00
Yuvi Panda
162ce2a9c5 Merge pull request #1178 from yuvipanda/auth-state
Encrypt auth_state at rest
2017-07-30 10:31:32 -07:00
Min RK
1f2125a097 Add Authenticator.enable_auth_state
Allows authenticators to optionally enable this flag

and signal that auth_state will be used,
enabling early check and exit if encryption is not available.
2017-07-28 22:36:49 +02:00
Matthias Bussonnier
feae3eacb1 Try enforcing methods overwrite at import time.
Currently Spawners need to overwrite start, stop, poll. When this is not
done, it will fail at runtime.

This replicate this check at class definition time, meaning that
potential errors will be caught way earlier. It also have not runtime
cost as the check is a class definition time (ie often import time).

This takes only effect on Python 3.6+ which introduce __init_subclass__,
we could do it with metaclasses, but that's might be too complicated.

If one want to create a class the avoid these restriction they can
overwrite __init_subclass__ and not call the super() method.
2017-07-28 12:05:18 -07:00
yuvipanda
a1a706cb31 More cleanup 2017-07-28 11:58:58 -07:00
Min RK
8a1da297d9 CryptKeeper is configurable 2017-07-28 17:20:57 +02:00
Min RK
1987221026 Python 3.4 doesn't allow bytestring formatting
can't do  until Python 3.5. When do we get to drop py34 support :)
2017-07-28 17:08:18 +02:00
Min RK
4b7b34064b alembic revision for encrypted_auth_state 2017-07-28 16:52:18 +02:00
Min RK
5abb4618bd test auth_state on login handler 2017-07-28 16:51:46 +02:00
Min RK
75c1d36237 trade privy for raw Fernet
only benefit of privy was KDF, but if users provide good 32B keys, this doesn't help.

Fernet already adds randomness, etc. to tokens, so is good enough on its own if keys are good.
2017-07-28 16:08:12 +02:00
Min RK
90e8e1a8aa move auth_state encryption outside the ORM
privy is used for encryption

- db only has blob column, no knowledge of encryption
- add CryptKeeper for handling encryption
- use privy for encryption, so we have fewer choices to make
- storing/loading encrypted auth_state runs in a ThreadPool
2017-07-28 16:08:12 +02:00
Min RK
32a9b38d26 use HKDF on auth keys
if the given tokens aren't already the right shape, pass through a proper KDF
2017-07-28 16:08:12 +02:00
Min RK
5714f56083 encrypt auth_state with MultiFernet
- MultFernet allows key rotation via `AUTH_STATE_KEY=secret2;secret1;secret0`
- Failure to decrypt results in cleared state
- Attempting to set auth_state without encryption is a hard failure
- Absent encryption, auth_state will always be None
2017-07-28 16:08:12 +02:00
Min RK
3d635816c9 add cryptography to dev requirements 2017-07-28 16:08:12 +02:00
yuvipanda
1aa5ce2f35 Add sqlalchemy-utils to requirements.txt 2017-07-28 16:08:12 +02:00
yuvipanda
f765fde6c1 Add OptionalEncrypted type 2017-07-28 16:08:12 +02:00
Min RK
523cbf641c Merge pull request #1288 from Carreau/fix-port-number
Default port is 8081 not 8080
2017-07-28 15:36:01 +02:00
yuvipanda
112834bbaa Cleanup code a little 2017-07-28 01:10:19 -07:00
Matthias Bussonnier
f0ab1ae907 Merge pull request #1286 from willingc/authenticator-edits
Refresh docs on Authenticators
2017-07-27 22:16:32 -07:00
yuvipanda
d6827a2794 Error if we hit pending spawn limit
The backlog actually doesn't help - almost all of them fail,
and the exponential backoff just adds more work for our ticks
2017-07-27 20:36:59 -07:00
Carol Willing
a1591185c1 Flesh out auth in swagger spec 2017-07-27 19:44:59 -07:00
Carol Willing
b77c8a8717 Update the API index section 2017-07-27 19:44:59 -07:00
Carol Willing
831b7d2a86 WIP 2017-07-27 19:44:59 -07:00
Carol Willing
057a52dd32 Add oauth to swagger api doc 2017-07-27 19:44:59 -07:00
Matthias Bussonnier
8f88fae530 Default port is 8081 not 8080 2017-07-27 19:21:16 -07:00
Carol Willing
85cc8eb6f3 Fix typo 2017-07-27 17:42:49 -07:00
Carol Willing
349f1b115e Reorganize content 2017-07-27 17:33:37 -07:00
yuvipanda
27de44b0ec Add support for limiting the number of concurrent spawns 2017-07-27 16:32:45 -07:00
Carol Willing
9847408d77 Edit auth docs 2017-07-27 08:59:57 -07:00
Carol Willing
cc24f36e80 Merge pull request #1281 from minrk/no-test-threads
eliminate test application thread
2017-07-27 08:43:45 -07:00
Min RK
e7fe6d25b6 set ASYNC_TEST_TIMEOUT=15 on Travis
Travis is super slow and default timeout is 5 seconds, which is too low sometimes.
2017-07-27 12:48:46 +02:00
Min RK
afc968146d fix race in test_proxy
prevent `.check_routes` from firing while we wait for a new proxy to come up

We check explicitly that it comes up with no routes, so makes sure check_routes hasn't restored its state, which is causing intermittent failures
2017-07-27 12:48:25 +02:00
Min RK
471decdbb6 Merge pull request #1280 from yuvipanda/hub_connect_port
Add hub_connect_port
2017-07-27 12:07:12 +02:00
Min RK
638f980281 fix race waiting for slow spawners
wait for `.running` instead of `._spawn_pending`,
since we now have `._proxy_pending` as well to wait for.
2017-07-27 11:46:33 +02:00
Min RK
8f1115a257 remove handling of changing db sessions
this was purely for accessing the db from multiple threads in tests
2017-07-27 11:37:19 +02:00
Min RK
9e8b6503a0 use gen_test in place of IOLoop.run_sync
even where not strictly required

for consistency, now that we are using gen_test on the main app tests
2017-07-27 11:29:58 +02:00
Min RK
91d042f6f3 get the rest of tests running without threads
all tests pass!
2017-07-27 11:29:58 +02:00
Min RK
d559cad042 test_pages without threads 2017-07-27 11:29:56 +02:00
Min RK
f05aecf5f9 test_api passes without threads
just put requests in a thread via `utils.async_requests`

eliminates db threads issue
2017-07-27 11:29:16 +02:00
Min RK
58f072e5af start MockHub without threads
everything's going to run with gen_test

need our own io_loop fixture that's module_scoped to go with our app fixture
2017-07-27 11:28:32 +02:00
yuvipanda
afc3bcbc75 Fix more references to port that should be connect_port 2017-07-26 18:12:01 -07:00
yuvipanda
8ee2fd2cf8 Fix possible redirect loop 2017-07-26 18:05:50 -07:00
yuvipanda
be7faacd07 Add ability to set hub_connect_port 2017-07-26 17:53:40 -07:00
Yuvi Panda
dc97433d9b Merge pull request #1272 from yuvipanda/exponential-function
Move exponential backoff into a function
2017-07-26 15:38:01 -07:00
Carol Willing
da10a8e7dd Edit docstring and comments 2017-07-26 13:00:16 -07:00
Carol Willing
847ae21ccb Merge pull request #1267 from minrk/auto-login
add login_user and get_next_url methods
2017-07-26 10:16:47 -07:00
Carol Willing
128cf115a7 Merge pull request #1269 from willingc/network-docs
Streamline networking and using REST API Docs
2017-07-26 09:50:49 -07:00
Carol Willing
1b9cff6d5f Add minrk comments 2017-07-26 09:48:58 -07:00
Carol Willing
110a8e22ae Edit for clarity 2017-07-26 09:26:21 -07:00
Carol Willing
7f058c0c77 Minor edits 2017-07-26 09:26:21 -07:00
Carol Willing
1e3512ac84 Update TOC placement 2017-07-26 09:26:21 -07:00
Carol Willing
8662a4a807 Edit networking and REST API usage docs 2017-07-26 09:26:21 -07:00
Carol Willing
63d1c918e5 Merge pull request #1276 from minrk/stop-button
running is a method now
2017-07-26 06:45:35 -07:00
Min RK
0a89090dc2 add login_user and get_next_url methods
for easier re-use of login in custom handlers

Further, enable auto_login + no custom login handler to mean that auth info is already present in requests
(e.g. REMOTE_USER)
2017-07-26 15:40:13 +02:00
Min RK
645575239f running is a method now
a few that were missed on the home page
2017-07-26 15:38:34 +02:00
Min RK
8de38b1708 add some jitter to the deadline itself
so that we don't re-align a bunch of timing out calls once the deadline is reached.

(±10% of timeout by default)
2017-07-26 14:12:28 +02:00
Min RK
6db987972a exponential backoff
- apply jitter to first iteration
- due to jitter, double start_wait to 0.2 so that <first wait> is still 0.1
- keep scaling by start_wait, rather than previous dt
- limit last wait to deadline so timeout is not overshot
2017-07-26 14:06:07 +02:00
Min RK
0ddf6bf579 restore wait_for_death
- don't raise TimeoutError
- keep Spawner.death_interval for subclasses
2017-07-26 14:06:07 +02:00
yuvipanda
9f8033a147 Move exponential backoff into a function
Also use the 'Full Jitter' jitter algorithm from
https://www.awsarchitectureblog.com/2015/03/backoff.html
2017-07-26 14:06:07 +02:00
Carol Willing
d007b40e15 Merge pull request #1275 from minrk/log-spawn-start
add log statement when spawn starts
2017-07-26 04:30:02 -07:00
Carol Willing
bbfd36fc92 Merge pull request #1274 from minrk/hub-token
simplify Hub object a bit
2017-07-26 04:24:24 -07:00
Min RK
3faa02b00d add log statement when spawn starts
for easier monitoring of spawn time
and improve consistency of named spawner logging
2017-07-26 12:57:15 +02:00
Min RK
eb1895e980 simplify Hub object a bit
- remove use of deprecated Hub.server
- add deprecation warning to Hub.server property
- move cookie_name declaration to Hub

It should now be possible to use Hub.from_url('http://1.2.3.4:1234/hub/') without missing information
2017-07-26 11:48:30 +02:00
Min RK
7ee8e96ece Merge pull request #1243 from minrk/named_servers
Flesh out named-servers
2017-07-26 11:15:16 +02:00
Min RK
3e796b579d Address review in named_servers
from willingc

- consistency of repr/str when logging usernames
- cleanup some attribute declarations
- add comments about db session weirdness
2017-07-26 10:47:35 +02:00
Carol Willing
74d9e2f421 Merge pull request #1268 from Carreau/flake8
Ignore a couple other of regularly non followed lint rules.
2017-07-25 13:58:47 -07:00
Matthias Bussonnier
2603cbb102 Ignore a couple other of regularly non followed lint rules.
These rules are not followed in a lot of place leading to too many
warnnigs which (at least in my editor) make code unreadable.
2017-07-25 13:50:13 -07:00
Min RK
194d6c9d4c Merge branch 'master' into named_servers 2017-07-25 18:29:01 +02:00
Yuvi Panda
f364f8e832 Merge pull request #1250 from yuvipanda/exponential-backoff-redirect
Apply exponential backoff when we're redirecting to ourselves
2017-07-25 08:19:10 -07:00
Carol Willing
ba6af85e9d Merge pull request #1264 from willingc/tech-overview
Streamline technical overview docs
2017-07-25 08:02:19 -07:00
Carol Willing
d2e411dba0 Edits per @minrk review 2017-07-25 08:01:14 -07:00
Min RK
e15a6bb758 Merge branch 'master' into named_servers 2017-07-25 16:56:16 +02:00
Carol Willing
96c04f3c60 Edit section intro 2017-07-25 07:49:06 -07:00
Carol Willing
9c9bc68092 Expand section overview and prune auth/spawners 2017-07-25 07:49:06 -07:00
Carol Willing
46f003fe14 Minor edits 2017-07-25 07:49:06 -07:00
Carol Willing
1404965b07 Edit and deduplicate the document text 2017-07-25 07:49:06 -07:00
Carol Willing
9fbb1417f2 Update table of contents 2017-07-25 07:49:06 -07:00
Carol Willing
158a7090a3 Combine tech overview docs into one 2017-07-25 07:49:06 -07:00
Carol Willing
9fa9859495 Move tech overview to config reference 2017-07-25 07:49:06 -07:00
Carol Willing
de85fefa7d Merge pull request #1262 from willingc/config-doc
Streamline configuration docs
2017-07-25 07:44:50 -07:00
Carol Willing
dee55df94a Edits per @minrk review 2017-07-25 07:43:48 -07:00
Carol Willing
62b9450ce1 Merge pull request #1266 from willingc/fix-link
Fix link to direct to docs not source
2017-07-25 07:07:32 -07:00
Carol Willing
bcdcf4351d Fix link to direct to docs not source 2017-07-25 07:04:47 -07:00
Min RK
0d941e9c96 move redirect loop fallback to /user/name handler
- add user_redirect_limit to settings, default 5 (that's still a whole minute before failing)
- limit sleep to ten seconds
2017-07-24 17:32:57 -07:00
yuvipanda
9d837b2e4b Add more docs & tweak max redirect wait time 2017-07-24 17:32:57 -07:00
yuvipanda
8544010eb6 Apply exponential backoff when we're redirecting to ourselves
Lots of custom proxy implementations that are distributed are
eventually consistent, and it might take upto a few seconds for
all the components to start redirecting properly. If we do
exponential backoff when doing these redirects, it gives the
proxies a lot of time to catch up. We also explicitly raise an
error if it's going on too long, instead of giving the user
juts a 'redirected too many times' error.
2017-07-24 17:32:57 -07:00
Carol Willing
f37243169a Update links 2017-07-24 14:30:05 -07:00
Yuvi Panda
7caa1e1f0e Merge pull request #1258 from minrk/salt-hash-uuid
don't salt & re-hash generated UUID tokens
2017-07-24 14:07:52 -07:00
Yuvi Panda
e019a394b0 Merge pull request #1259 from willingc/fix-docstring
Reformat docstring causing Sphinx error
2017-07-24 14:06:25 -07:00
Carol Willing
c0b482e68c Fix typos 2017-07-24 08:57:25 -07:00
Carol Willing
2da115f5c4 Reformat docstring causing Sphinx error 2017-07-24 08:32:12 -07:00
Min RK
639ccf5582 index prefix column 2017-07-24 17:27:19 +02:00
Min RK
2654794968 don't salt & extra hash uuids
They have enough entropy on their own,
so use just the hash and no salt.

ref: https://security.stackexchange.com/a/151262/155114
2017-07-24 17:03:04 +02:00
Min RK
2cec124b4f support named servers in REST API
and exercise them in tests
2017-07-24 16:55:17 +02:00
Carol Willing
e21737399b Edit config basics doc and examples 2017-07-24 07:53:20 -07:00
Min RK
9a555d8a6e move user.proxy_pending to Spawner._proxy_pending 2017-07-24 15:22:36 +02:00
Min RK
f7bf2b0ba6 Merge branch 'master' into named_servers 2017-07-24 15:21:42 +02:00
Min RK
710ed0a5c8 Merge pull request #1245 from willingc/deduplicate
Review and edit security documentation
2017-07-24 14:35:33 +02:00
Min RK
7539523ef2 Merge pull request #1251 from yuvipanda/another-race-maybe
Don't add route if there's already a route addition pending
2017-07-24 14:34:34 +02:00
Yuvi Panda
c97444e438 Merge pull request #1257 from minrk/dirty
Dirty database fixes
2017-07-24 05:19:19 -07:00
Min RK
4c86d10037 comment about sqlachemy dirty flag 2017-07-24 14:12:50 +02:00
Min RK
69a6c79558 use admin user in test_admin
rather than relying on multi db sessions talking to each other
2017-07-24 13:37:11 +02:00
yuvipanda
a0466dc322 Count ourselves as a good route if we've a proxy pending 2017-07-24 04:35:13 -07:00
Min RK
546e35e9a3 Merge pull request #1249 from Carreau/fix-pam-500
Do not 500 if cannot authenticate.
2017-07-24 12:54:56 +02:00
Min RK
ce53b11cf7 Make rollback conditional on db.dirty
avoids calling rollback when there are no changes

includes warning about what objects are actually dirty
2017-07-24 12:53:58 +02:00
Min RK
1229fd100f only set attributes on orm_server if they changed
Setting things on orm_server set the dirty flag,
even if they haven't changed.
2017-07-24 12:52:46 +02:00
Matthias Bussonnier
e4541591ea Do not 500 if cannot authenticate.
self.authenticate can return None, in which case you can't subscript.
So move extracting data into the branch checking whether authenticate is
not `None`.

Now that extracting the username is inside the if branch, it can't be
used in the else one, so extract username from the request itself.

This can be easily reproduce with the default PAM login with a wrong
non existing/ wrong username.
2017-07-21 15:40:28 -07:00
Carol Willing
be62b1b9df Reword based on @minrk's review 2017-07-21 11:47:24 -07:00
Carol Willing
9c21cf4c62 Add @minrk review comments 2017-07-21 11:32:48 -07:00
Carol Willing
51af6a98cc Be clearer about the config file name 2017-07-21 11:23:43 -07:00
Carol Willing
520d6160f0 Make use of config file and environment variable consistent 2017-07-21 11:23:43 -07:00
Carol Willing
e8ebedb2da Move security audits to overview doc 2017-07-21 11:23:43 -07:00
Carol Willing
fd7700d577 Update title 2017-07-21 11:23:43 -07:00
Carol Willing
6ee88a5424 Edit content for clarity 2017-07-21 11:23:43 -07:00
Carol Willing
c89711d0d5 Edit and deduplicate security docs 2017-07-21 11:23:43 -07:00
Carol Willing
daee0f8df8 Merge pull request #1248 from Carreau/cleanup
Remove unused import and add version to deprecations.
2017-07-21 11:21:20 -07:00
Matthias Bussonnier
e1444f4aca remove trailing comma 2017-07-21 11:13:18 -07:00
Matthias Bussonnier
97b9c4899a typo 2017-07-21 11:12:24 -07:00
Matthias Bussonnier
b8aa6ecd70 Remove unused import and add version to deprecations. 2017-07-21 10:23:54 -07:00
Min RK
e28f3947bd Merge branch 'master' into named_servers 2017-07-21 15:43:09 +02:00
Min RK
bc9cc98789 Merge pull request #1246 from yuvipanda/no-unconditional-add
Don't unconditionally add hub route to proxy
2017-07-21 10:23:25 +02:00
yuvipanda
72132e7946 Don't unconditionally add hub route to proxy
This is done contidtionally in check_routes instead
2017-07-21 01:01:21 -07:00
Carol Willing
b0307dd98e Merge pull request #1242 from minrk/headers-fixes
various singleuser header fixes
2017-07-20 11:49:13 -07:00
Carol Willing
fd1ac55a70 Merge pull request #1240 from minrk/drop-33
Require Python 3.4
2017-07-20 11:25:30 -07:00
Yuvi Panda
39d8800389 Merge pull request #1241 from minrk/progress-spin
add spinner to slow-spawn page
2017-07-20 09:59:32 -07:00
Min RK
382a7121e1 further clear up named servers
- use spawner.server instead of user.server
- user.running, proxy_spec are methods that take spawner names
2017-07-20 16:54:17 +02:00
Min RK
4c0ac6d502 Merge pull request #1234 from CRegenschein/master
Add pre_spawn_hook
2017-07-20 15:45:06 +02:00
Min RK
40dcbedc2a various singleuser header fixes
- always set content security policy header, to workaround bug in notebook 5.0
- set x-jupyterhub-version on all requests, not just our own
- fix version comparison in _check_version (leftover `__version__`)
- even log version matches at debug-level (verifies that check happened)
2017-07-20 15:37:54 +02:00
Min RK
9eda66b3ae bump bower dependencies
need fa 4.3 for fa-pulse, but rev everything while we're at it
2017-07-20 14:31:13 +02:00
Min RK
d4c48db248 add spinner on slow-spawn page 2017-07-20 14:30:45 +02:00
Min RK
7bd4861689 minor cleanup in pre_spawn_hook
- remove reduntant None, allow_none in Any
- remove callable check (if it's not callable, let the error raise)
- let outer error handling deal with failed pre-spawn hook
- add missing `return` in pre_spawn_hook
2017-07-20 14:08:06 +02:00
CRegenschein
72550725da jupyterhub-1219 Enhancement: automatically create a directory for the user after successful login 2017-07-20 14:02:13 +02:00
Min RK
5a8011ea66 Require Python 3.4
Specify Requires-Python (PEP345) metadata
2017-07-20 13:49:34 +02:00
Min RK
0fd1a95405 Merge pull request #1239 from willingc/remove-33
Bump Python support to 3.4 and up
2017-07-20 13:48:56 +02:00
Min RK
8d0cfa8e7c always set content-type json on API handlers 2017-07-20 11:58:50 +02:00
Min RK
3d1187283c apply stricter CSP on api endpoints
double-ensure that no scripts run on api pages (referrer check already doesn't allow malicious links)
2017-07-20 11:58:50 +02:00
Carol Willing
7416a55083 Add test for invalid version 2017-07-19 19:23:37 -07:00
Carol Willing
e8a3c4dac6 Fix link 2017-07-19 17:33:14 -07:00
Carol Willing
33f2026dac Add badge for 0.7.2 docs to README 2017-07-19 17:30:57 -07:00
Carol Willing
d34f6e779d Bump Python support to 3.4 and up 2017-07-19 14:57:52 -07:00
Min RK
738976a956 Merge pull request #1236 from willingc/doc-intro
Break up long Getting Started doc page
2017-07-19 11:40:39 +02:00
Carol Willing
fd8cc1df15 Break up large getting started doc 2017-07-18 17:57:56 -07:00
Carol Willing
61053b063e Reorganize content 2017-07-18 16:47:11 -07:00
Carol Willing
a27e1e9d40 Break up installation document 2017-07-18 11:45:03 -07:00
Carol Willing
a7889eb536 Rename guide to reference 2017-07-18 11:03:49 -07:00
Carol Willing
0f17709d4e Edit content in intro 2017-07-18 11:03:13 -07:00
Min RK
3eca010f66 limit curl logging to INFO-level
curl debug logs every byte of every request
2017-07-18 14:49:13 +02:00
Min RK
041ffd6db2 support named servers in proxy 2017-07-18 14:48:51 +02:00
Min RK
4b5aad41b1 make user.running a method
accept server names
2017-07-18 14:48:29 +02:00
Min RK
d6565076f5 add admin user by default 2017-07-18 14:29:59 +02:00
Min RK
c943162649 merge named server handlers
only need one handler class per path
2017-07-18 14:28:45 +02:00
Min RK
a2e94b8493 create Spawners table
for named servers

removes User.servers
2017-07-18 14:28:31 +02:00
Min RK
94b2bc1261 Merge pull request #1231 from willingc/doc-refresh
Update docs main TOC and edit quickstart
2017-07-18 13:19:45 +02:00
Min RK
7d34f83b18 Merge pull request #1232 from dhirschfeld/win-fix3
Pass `shell=True` to `check_call` on Windows
2017-07-18 13:18:54 +02:00
Hirschfeld
4f27a18616 Pass shell=True to check_call on Windows 2017-07-18 12:15:33 +10:00
Carol Willing
5a5aa1c2aa Update main TOC and edit quickstart 2017-07-17 12:24:43 -07:00
Carol Willing
1bafdf9130 Merge pull request #1223 from minrk/wait-up-fall-off
apply exponential backoff to all waits
2017-07-17 09:15:48 -07:00
Min RK
9eef5d7b1e refresh session of spawner server 2017-07-17 11:05:25 +02:00
Min RK
aee3c74681 Merge origin/master into named_servers 2017-07-17 10:53:17 +02:00
Min RK
653a39c05e checkpoint: named server state 2017-07-17 10:41:36 +02:00
Min RK
efa6a33b0a variables for exponential falloff 2017-07-17 10:27:42 +02:00
Min RK
0c5a9e8347 Merge pull request #1225 from willingc/unofficial-win
Document more fully platform support
2017-07-17 10:24:54 +02:00
Min RK
657f77b7c6 Merge pull request #1224 from dhirschfeld/more-windows-fixes
More Windows Fixes
2017-07-17 10:23:50 +02:00
Carol Willing
b528572960 Document in more detail platform support 2017-07-16 19:13:54 -07:00
Hirschfeld
e75d24aca2 Create getgrnam wrapper function to allow mocking in tests 2017-07-17 11:38:04 +10:00
Hirschfeld
7607f8d639 More Windows fixes 2017-07-17 11:13:00 +10:00
Carol Willing
9a59c02077 Merge pull request #1220 from minrk/service-msg
fix filtering of services with no endpoint
2017-07-16 08:46:54 -07:00
Min RK
8e3c4b1925 apply exponential backoff to all waits
Waiting for servers to come up and shut down was polled at an even interval of 100ms. If things are slow and busy, this is a lot if waiting events. exponential backoff reduces the number of callbacks triggered by slow spawners.

This may improve the load a bit when there’s a bunch of outstanding spawns.
2017-07-15 12:56:47 +02:00
Yuvi Panda
057bf03d3a Merge pull request #1221 from minrk/proxy-race
add User.proxy_pending
2017-07-14 19:20:16 -07:00
Min RK
224faff879 Merge pull request #1208 from dhirschfeld/windows-fixes
Minor fixes to get setup.py to work on Windows
2017-07-14 17:28:28 +02:00
Min RK
a6c2939bb4 delay stop_pending until the end of stop
avoids stop_pending being False while there's still one yield to go
2017-07-14 15:53:38 +02:00
Min RK
c78d88707c fallback during initial hub connection 2017-07-14 15:34:34 +02:00
Min RK
a79071bb33 add User.proxy_pending
flag for waiting for the proxy to be updated

avoids User.running being True when the user's server has not yet been added to the proxy,
causing potential redirect loops.
2017-07-14 15:17:56 +02:00
Min RK
dca530d2c0 Merge pull request #1218 from minrk/raise-not-exit
fix leftover `self.exit` in proxy
2017-07-14 14:13:17 +02:00
Min RK
c5b1542af2 fix service filtering
use `!=` to check for None, not `is not`
2017-07-14 14:11:25 +02:00
Min RK
a13e7766fc fix leftover self.exit in proxy
self.exit is a method on Application, missed copying the proxy code out of the JupyterHub app.
2017-07-14 10:51:14 +02:00
Min RK
765e391810 Merge pull request #1214 from yuvipanda/hub_ip_connect_config
Tag hub_ip_connect as configurable
2017-07-14 10:44:09 +02:00
Yuvi Panda
6a12e78cee Merge pull request #1212 from yuvipanda/typo-fix
Fix typo in proxy implementation
2017-07-13 21:15:17 -07:00
yuvipanda
e0effa567a Tag hub_ip_connect as configurable
This value is expected to be provided by the user.
2017-07-13 20:14:11 -07:00
yuvipanda
0322ca6d05 Fix typo
It is now self.command, not cmd
2017-07-13 19:52:13 -07:00
Hirschfeld
13eda34676 Used os.pathsep to join paths 2017-07-13 22:19:37 +10:00
Hirschfeld
874ed0c450 Passed shell argument to check_call instead of calling cmd.exe directly 2017-07-13 22:15:19 +10:00
Hirschfeld
f25ec3c3f0 Minor fixes to get setup.py to work on Windows 2017-07-13 16:47:26 +10:00
Carol Willing
8373c4619e Merge pull request #1207 from minrk/check-routes-on-startup
check routes on startup
2017-07-12 08:56:14 -05:00
Min RK
549dfd99e5 check routes on startup
and be more thorough about clearing out stale routes that shouldn't be there
2017-07-12 14:06:04 +02:00
Carol Willing
eed88f6366 Merge pull request #1204 from minrk/httponly
set httponly on cookies
2017-07-11 09:33:00 -05:00
Carol Willing
fcf745b2f4 Merge pull request #1206 from minrk/pycurl-by-default
use pycurl by default, if available
2017-07-11 09:31:58 -05:00
Min RK
69a27b7843 use pycurl by default, if available
simplehttpclient can have issues with high load
2017-07-11 16:16:02 +02:00
Min RK
a51141810d set httponly on cookies 2017-07-11 11:06:00 +02:00
Yuvi Panda
396f454998 Merge pull request #1199 from jupyterhub/data-dict-default
Make data a non-optional arg to add_route
2017-06-29 14:06:00 -07:00
yuvipanda
5f21909138 Fix proxy test failure 2017-06-29 12:32:31 -07:00
yuvipanda
ebb7b4b4ae Make data a non-optional arg to add_route
We expect at least an empty dict when we fetch it,
so let's make it non-optional and always pass in something.
This is clearer.
2017-06-29 12:26:27 -07:00
Min RK
e691231f64 Merge pull request #1169 from minrk/version-check
Compare JupyterHub and single-user server versions
2017-06-29 17:49:22 +01:00
Min RK
471110c0f2 Merge pull request #1194 from yuvipanda/route_fix
Mark `data` param to proxy.add_route optional
2017-06-29 06:52:14 +01:00
yuvipanda
73948c016b Mark data param to proxy.add_route optional
It is used as optional throughout the code, and the CHP implementation
makes it optional too. So let's explicitly mark it as such.
2017-06-28 22:40:52 -07:00
Carol Willing
864e7ac4ee Merge pull request #1193 from willingc/rtd-update
Remove mkdocs as workaround fixed in RTD upstream
2017-06-28 15:53:07 -07:00
Carol Willing
2207220592 Remove mkdocs as workaround fixed upstream 2017-06-28 15:50:35 -07:00
Min RK
a4a5781f7f invoke app when testing single-user 2017-06-28 21:55:15 +01:00
Min RK
194d2b9639 handle oauth id checks in tests 2017-06-28 21:55:15 +01:00
Min RK
530f499ce1 _version.py is private 2017-06-28 21:55:15 +01:00
Min RK
d167e275d1 compare hub and single-user server versions
in both directions - Hub checks singleuser server on spawn and singleuser server checks Hub on startup

if minor versions mismatch, log at warning level, otherwise debug
2017-06-28 21:55:15 +01:00
Min RK
cdcc7fc3c1 return http response from wait_for_http_server 2017-06-28 21:55:15 +01:00
Min RK
0a30e0ade5 put jupyterhub version in logs and headers 2017-06-28 21:55:15 +01:00
Min RK
47dc66db5a better handle a few values being undefined when launching single-user 2017-06-28 21:55:15 +01:00
Yuvi Panda
c192391551 Merge pull request #1189 from minrk/default-route
add default hub route via Proxy.add_route
2017-06-28 12:58:30 -07:00
Carol Willing
b0c44aa67a Merge pull request #1192 from willingc/fix-conda
Add mkdocs as RTD workaround
2017-06-28 08:21:48 -07:00
Carol Willing
29890dcfa9 Add mkdocs as RTD workaround 2017-06-28 04:46:06 -07:00
Min RK
1742065f77 Merge pull request #1191 from kroq-gar78/fix-anchors
Fix in-document anchors
2017-06-28 10:36:14 +01:00
Aditya Vaidya
28480d0359 Fix in-document anchors
Removes the explicit extension of the target if it's in the same
document. This allows these links to work in GitHub or in Read the Docs.
2017-06-28 01:57:45 -07:00
Min RK
2f57cfc812 respect port in testing subdomain host 2017-06-28 09:53:57 +01:00
Min RK
b12a52e266 run tests -v 2017-06-28 09:50:07 +01:00
Min RK
5d45a44247 use db_factory in Proxy
should avoid session crossover problems in tests

…still really need to move tests over to gen_test
2017-06-27 22:39:39 +01:00
Min RK
8ee520d99b filter out non-jupyterhub routes in CHP 2017-06-27 15:22:26 +01:00
Min RK
4c0d4ffc47 add default hub route via Proxy.add_route
instead of relying on default target
2017-06-27 15:22:26 +01:00
Min RK
44c00a2581 run test hub on a random port 2017-06-27 15:22:26 +01:00
Min RK
1015f3bf53 Merge pull request #1187 from minrk/fix-db
fix db reconnect when user.db changes
2017-06-27 15:21:20 +01:00
Yuvi Panda
71378d23d5 Merge pull request #1180 from minrk/auth-return-dict
allow .authenticate to return a dict containing name and state
2017-06-26 10:23:39 -07:00
Yuvi Panda
f5d0855c2b Merge pull request #1177 from minrk/proxy-routespec
define routespec
2017-06-26 10:05:07 -07:00
Min RK
88040362b0 fix db reconnect when user.db changes
store id on outer User, rather than accessing orm_user.id, which seems to fail sometimes

this may fix the recent increase in intermittent test failures
2017-06-26 12:46:55 +02:00
Min RK
8f49412438 docstrings for proxy 2017-06-26 11:32:15 +02:00
Min RK
bb417b98b8 Merge pull request #1184 from evanlinde/evanlinde-patch-1
Add '/tree' to spawner default_url
2017-06-25 08:36:18 +02:00
evanlinde
afed81d173 Fix default_url documentation 2017-06-24 23:07:31 -05:00
evanlinde
def99c1795 Add '/tree' to default_url
Add '/tree' to default_url so it doesn't have to be included in config file.
2017-06-23 16:22:41 -05:00
evanlinde
fcdea007ac Merge pull request #1 from jupyterhub/master
Trying to update local copy
2017-06-23 13:51:10 -05:00
Min RK
383b56276e fix versionchanged format 2017-06-23 18:51:51 +02:00
Min RK
11e6c38702 routespecs are strings (again)
- no slash means host-routing
- slash means no-host
2017-06-23 14:49:42 +02:00
Min RK
a2686ac27b always return dict from get_authenticated_user
outer APIs don't need to handle the different cases
2017-06-23 14:41:06 +02:00
Min RK
49bf4747fd avoid error in service.stop if service failed to start 2017-06-23 14:12:31 +02:00
Min RK
cf257c48b4 handle host-routing in add/get/delete 2017-06-23 14:12:31 +02:00
Min RK
05d939beac JSON shenanigans now that proxy route keys aren't strings 2017-06-23 14:12:31 +02:00
Min RK
fa7fed8ea3 routespec docstrings 2017-06-23 14:12:31 +02:00
Min RK
fbf5816952 handle leading/trailing slashes in RouteSpec 2017-06-23 14:12:31 +02:00
Min RK
31fc89c944 add RouteSpec namedtuple for route specification
namedtuple(path, host)

everywhere that accepts a RouteSpec must also accept a string
and treat it as RouteSpec(string).
RouteSpec.as_routespec(spec_or_string) handles this.
2017-06-23 14:12:30 +02:00
Min RK
f7a05713a1 allow .authenticate to return a dict containing name and state
Allows authenticators to set .auth_state from info in the initial authentication.
2017-06-22 15:19:45 +02:00
Yuvi Panda
9f532d6b2d Merge pull request #1176 from minrk/protect-pamela
delay errors on pamela import
2017-06-21 08:58:12 -07:00
Min RK
5263e4ceae user.state is keyed by server name 2017-06-21 16:52:54 +02:00
Min RK
3145011004 add multi-spawner info to user model 2017-06-21 16:33:39 +02:00
Min RK
5da4348c2d move some state to Spawner
now that there are more than one per user
2017-06-21 16:33:16 +02:00
Min RK
e33e34748f Re-sync with master 2017-06-21 15:33:01 +02:00
Min RK
d2e62a90d7 Merge pull request #1167 from minrk/more-env-less-argv
pass more arguments as environment variables instead of CLI args
2017-06-21 14:13:25 +02:00
Min RK
593a3c8ebb fix base_url handling in services
JUPYTERHUB_BASE_URL is the whole application base_url (default: /)
JUPYTERHUB_SERVICE_PREFIX is the service prefix (/user/name/)
2017-06-21 14:02:55 +02:00
Min RK
6713277f33 delay errors on pamela import
only raise ImportError on pamela if PAMAuthenticator is actually used

avoids failure to start in rare cases where pamela is not importable (e.g. broken libpam)
2017-06-21 11:17:13 +02:00
Min RK
178f1ed5e0 fix defaults in singleuser ip/port
when service url is undefined

never return None
2017-06-15 11:08:35 +02:00
Min RK
f5c703a04f update tests for env change 2017-06-15 11:08:35 +02:00
Min RK
27e83a3260 pass more arguments as environment variables instead of CLI args
env is often easier to deal with for Spawners

Now, only optional args are passed on the command-line and all required args come from environment variables.
2017-06-15 11:08:33 +02:00
Carol Willing
e7cd5ec019 Merge pull request #1170 from minrk/403-bad-user
raise 403 on disallowed user, rather than redirect to login
2017-06-14 15:12:35 -07:00
Min RK
8704deeb31 ensure db.commit happens before yield 2017-06-14 21:19:38 +02:00
Min RK
9c6056518f use user.base_url in args 2017-06-14 21:18:38 +02:00
Min RK
5f813a4206 Merge pull request #1172 from Carreau/intersphinx-python-3
Inter-sphinx with Python 3, not 2.
2017-06-13 10:27:42 +02:00
Matthias Bussonnier
5cb40531d0 Inter-sphinx with Python 3, not 2.
Python 2 is the default, you need to be explicit for Python 3.
2017-06-12 12:04:41 -07:00
Min RK
fe85a79ae3 403 in services_auth tests 2017-06-08 19:00:35 +02:00
Min RK
97ec0b803d Merge pull request #1171 from minrk/close-socket
close socket when testing connections
2017-06-08 18:57:30 +02:00
Min RK
a5fbc0351f close socket when testing connections
rather than relying on garbage collection
2017-06-08 15:28:02 +02:00
Yuvi Panda
38e772dfec Merge pull request #1165 from minrk/hub_connect_ip
add hub_connect_ip
2017-06-07 14:32:40 -07:00
Min RK
dda3762b48 raise 403 on disallowed user, rather than redirect to login url
raise UserNotAllowed exception in generic `check_hub_user`
when a user or service is identified and not allowed.

turn it into `HTTPError(403)` in tornado `get_current_user` wrapper,
caching `None` so that subsequent calls don't re-trigger the same error.
2017-06-07 15:30:12 +02:00
Min RK
1ddbf97c11 comments to clarify that connect_ip is only for connecting 2017-06-07 13:21:52 +02:00
Min RK
ca4952a85d Merge pull request #1166 from minrk/log-cleanup
disconnect logging during MockHub cleanup
2017-06-06 18:39:56 +02:00
Min RK
d76632de91 update tests for connect_ip changes 2017-06-06 16:33:30 +02:00
Min RK
b96f3485fd make connect_ip a property
so that the default doesn't override explicit settings
2017-06-06 16:33:30 +02:00
Min RK
a6f1f6ea09 disconnect logging during MockHub cleanup
pytest appears to close captured FDs prematurely,
causing huge "I/O operation on closed file" tracebacks
whenever tests stop early due to a failure.

This should quiet the extra traceback, though it could potentially silence useful log messages during cleanup in rare cases
2017-06-06 15:28:19 +02:00
Min RK
d2533688b6 add hub_connect_ip
allows specifying the connect ip/hostname for the Hub
when it differs from hub_ip (the bind address).

Used when the Hub is not on the same host as the spawners and/or proxy (e.g. docker, kubernetes, etc.)
2017-06-06 12:47:43 +02:00
Min RK
6810aba5e9 Merge pull request #1164 from joychak/master
Added Kerberos authenticator link for Jupyterhub in ReadMe file
2017-06-06 10:09:12 +02:00
jchakrabort5
aca5b1ccd4 Added Kerberos authenticator for Jupyterhub in ReadMe 2017-06-05 10:00:16 -04:00
Carol Willing
888aa99ea6 Merge pull request #1069 from minrk/first-poll-fails-no-crash
Prevent crashes due to deleted system users
2017-06-02 05:25:34 -07:00
Min RK
b112b88587 Merge pull request #1148 from yuvipanda/pwdfree
Don't use getuser to find out current user name for spawning
2017-05-22 16:40:14 -07:00
Carol Willing
86276541be Merge pull request #1146 from minrk/log-redirect-targets
log redirect targets
2017-05-22 15:18:31 -07:00
Carol Willing
bdfd81fe83 Merge pull request #1144 from minrk/raise-on-config-error
raise on config file errors
2017-05-22 15:16:05 -07:00
Min RK
c24a0a4995 typo missing hub.api_url in service 2017-05-22 15:09:31 -07:00
Min RK
524b9104d0 also skip user_env for no username 2017-05-22 15:09:01 -07:00
Min RK
19e896c38d Merge pull request #1143 from minrk/spawn-next-url
Don’t redirect back to home from spawn
2017-05-22 14:39:58 -07:00
Min RK
62517d0c89 Merge pull request #1098 from minrk/proxy
implement proxy API
2017-05-22 14:17:41 -07:00
yuvipanda
49a0f154d0 Don't use getuser to find out current user name for spawning
It can easily be spoofed, since it only looks at env vars
2017-05-22 14:17:19 -07:00
Min RK
39248a532d log redirect targets
on both Hub and singleuser

should help debugging redirect loops, etc.
2017-05-21 11:04:15 -07:00
Min RK
465c81f281 clarify delete-invalid-user messages and docstrings 2017-05-20 11:31:59 -07:00
Min RK
2d8facd022 Add Authenticator.delete_invalid_users
opt-in option for deleting users that have been invalidated,
e.g. for LocalAuthenticators when system users have been removed and `create_system_users` is False.

Since it’s opt-in, log config to do so when the error is seen and option is not enabled.
2017-05-20 11:21:21 -07:00
Min RK
d548aa1e72 deprecate old proxy config
but keep it working with warnings
2017-05-19 12:08:49 -07:00
Min RK
7968912a7c raise on config file errors
don’t start jupyterhub if we can’t load config files
2017-05-19 11:43:59 -07:00
Min RK
79bd1a50ad Don’t redirect back to home from spawn
options_form spawn sent people back to home instead of to their newly spawned server
2017-05-19 11:42:58 -07:00
Carol Willing
7b96950a9c Merge pull request #1139 from tschaume/patch-1
semi-colons missing
2017-05-16 18:49:48 -07:00
Patrick Huck
89331d15cc semi-colons missing 2017-05-16 15:44:47 -07:00
Carol Willing
25910b732a Merge pull request #1132 from minrk/stop-docstring
Correct stop docstring
2017-05-16 13:21:56 -07:00
Min RK
bdcb9e7540 Correct stop docstring
stop should always wait to finish,
`now` indicates how forcefully it should be done.
2017-05-15 09:33:23 +02:00
Min RK
130bec4a2f Merge pull request #1133 from willingc/travis-requests
Update pip before install of dependencies on travis
2017-05-10 22:05:27 +02:00
Carol Willing
db2d685c40 Update pip before install dependencies on travis 2017-05-09 10:32:47 -07:00
Carol Willing
f9e0f90e08 Merge pull request #1119 from minrk/next-url
include next_url in authenticator login url
2017-05-08 03:05:56 -07:00
Carol Willing
4f85644c34 Merge pull request #1131 from minrk/clear-poll-notify
clear poll callbacks list before using it
2017-05-08 03:04:00 -07:00
Min RK
73d77ee56b clear poll callbacks list before using it
avoids accumulating callbacks for repeated spawns
2017-05-08 11:34:24 +02:00
Min RK
33a37ffa25 User has no single .server anymore 2017-05-08 11:07:35 +02:00
Carol Willing
2716ba4dc6 Merge pull request #1129 from charnpreetsingh/docs-warning
add jupyterhub-deployment-aws in docs
2017-05-06 17:35:00 -07:00
Carol Willing
65afc65f51 Merge pull request #1130 from willingc/new-docs
Update docs for jupyter alabaster theme
2017-05-06 17:20:34 -07:00
Carol Willing
034432bfba Remove self from contents 2017-05-06 16:51:29 -07:00
Carol Willing
f815fe8b59 Update for jupyter-alabaster local build 2017-05-06 16:46:48 -07:00
Carol Willing
cc7605d6a9 Add subsection docs 2017-05-06 16:46:48 -07:00
Carol Willing
d809b8717c Add numbered, self, and order in index 2017-05-06 16:46:48 -07:00
Carol Willing
f878ad54a8 Change single toc tree to visible and numbered 2017-05-06 16:46:48 -07:00
Carol Willing
22bc9b0dbf Make a single toctree 2017-05-06 16:46:48 -07:00
Carol Willing
86428aa0f6 Change to jupyter alabaster doc theme 2017-05-06 16:46:48 -07:00
charnpreetsingh
8c8b532ffd add jupyterhub-deployment-aws 2017-05-05 12:55:59 -07:00
Min RK
475c0a3144 Merge pull request #1127 from minrk/sudo-false
set sudo: false on Travis
2017-05-04 16:27:52 +02:00
Min RK
3c6e20585c set sudo: false on Travis 2017-05-04 14:03:19 +02:00
Min RK
98c2bd9a6a return ip, port from stub spawner
avoids deprecation warning in tests
2017-05-04 13:49:31 +02:00
Min RK
226b6c40a5 improve waiting for service to start in mockservice fixture
- wait for proxy update before starting service
- wait for service server to respond to start before proceeding
2017-05-04 13:33:16 +02:00
Min RK
4cb18c931d JUPYTERHUB_HOST is hub.public_host 2017-05-04 13:24:04 +02:00
Min RK
96b75c18b7 fix check-routes data access 2017-05-04 13:23:53 +02:00
Min RK
87d9d14e5d update proxy test 2017-05-04 12:28:37 +02:00
Min RK
1069799ea7 get rid of single-user cookie_name
it's unused now that single-user uses OAuth
2017-05-04 12:20:02 +02:00
Min RK
5e55753baa various cleanup to get most tests passing (yay!) 2017-05-04 12:16:47 +02:00
Min RK
be8f847309 move proxy management to Proxy object
out of the Application
2017-05-04 11:13:19 +02:00
Min RK
acc31b8441 remove Hub, Proxy from database
These are in-memory-only objects, no need for a table with one row
2017-05-04 11:05:58 +02:00
YuviPanda
a98bab8b5e Mock of how the proxy base class will be used 2017-05-04 11:02:33 +02:00
YuviPanda
7b944a3a3f Add proxy base class 2017-05-04 11:02:33 +02:00
Carol Willing
a0d32c5b33 Merge pull request #1126 from charnpreetsingh/dependencies
Sphinx min version is 1.4
2017-05-03 17:06:17 -07:00
charnpreetsingh
89f1254396 resolve merge conflicts 2017-05-03 16:06:57 -07:00
charnpreetsingh
41c136392f Sphinx min version is 1.4 2017-05-03 16:00:31 -07:00
Min RK
b4d1ee353d include next_url in authenticator login url
avoids losing redirect target when clicking through "Login with ..."
2017-05-02 14:37:52 +02:00
Carol Willing
a24d7406fc Merge pull request #1097 from minrk/whoami-only
Don't give OAuth access tokens access to the REST API
2017-05-02 03:03:58 -07:00
Min RK
574d3ba1f4 unused imports 2017-05-02 11:10:06 +02:00
Carol Willing
6eb61e2923 Merge pull request #1111 from minrk/whitespace-password
avoid stripping login form fields
2017-04-28 09:57:05 -07:00
Min RK
9e679e8024 avoid stripping login form fields
which prevented users from being able to login with passwords that start or end with whitespace
2017-04-28 16:40:11 +02:00
Carol Willing
006488fc74 Merge pull request #1101 from prasadkatti/patch-1
[docs] Minor fix to index.rst
2017-04-23 22:06:22 -04:00
Prasad Katti
8e66c383e8 [docs] Minor fix to index.rst 2017-04-23 11:12:34 -07:00
Carol Willing
e7a0556118 Merge pull request #1066 from minrk/auto_login
make Authenticator.auto_login explicit
2017-04-22 07:02:04 -04:00
Min RK
6117c0b573 accept OAuthAccessTokens in /authorization/token 2017-04-21 14:52:47 +02:00
Min RK
c3a90e0804 raise 500 on failure to identify a user in oauth callback 2017-04-21 14:52:23 +02:00
Min RK
66cb630b86 separate OAuth access tokens from API tokens
OAuth access tokens can only be used to identify users, not perform actions on their behalf, which API tokens do.

Implementing OAuth scopes would allow us to achieve this limitation without separating the two items, but that would be a much bigger change, including having an OAuth "Would you like to grant permissions..." confirmation page.
2017-04-21 14:52:07 +02:00
Christian Barra
2b2eefdd1f catch KeyError for get_spawner 2017-04-19 14:58:43 +02:00
Christian Barra
db77932a95 moving track of spawner's instances inside user 2017-04-19 14:46:54 +02:00
Christian Barra
2aaf82412d add a dict to save spawner's instances, fix user.server with server 2017-04-19 03:25:26 +02:00
Min RK
4df93cab04 add oauth2 to doc requirements 2017-04-18 16:16:16 +02:00
Carol Willing
b778232cac Merge pull request #1090 from minrk/rm-other-user-cookies
remove references to unused other_user_cookies
2017-04-18 07:05:41 -07:00
Min RK
f58015dc57 remove references to unused other_user_cookies
OAuth gets rid of the concept of the Hub managing cookies on behalf of sub-servers
2017-04-18 11:22:00 +02:00
Min RK
57d3cbccc4 Merge pull request #1084 from prasadkatti/patch-2
Fix Travis CI url
2017-04-18 11:18:59 +02:00
Prasad Katti
52fdd0bd8c Fix Travis CI url 2017-04-15 17:50:23 -07:00
Christian Barra
ced8e9f874 add named_servers proxy 2017-04-15 05:22:01 +03:00
Christian Barra
76b589bc90 fix named_servers, change server.base_url 2017-04-15 03:47:09 +03:00
Carol Willing
4c79a8cb2d Merge pull request #1077 from willingc/ipython-profile
Remove reference to profile for Jupyter
2017-04-13 07:28:53 -07:00
Carol Willing
64f7244808 Remove reference to profile for Jupyter 2017-04-13 07:27:07 -07:00
Carol Willing
ebaf36d503 Merge pull request #1072 from willingc/docker-docs
Add information about DockerHub to FAQ
2017-04-13 07:18:27 -07:00
Carol Willing
e58c1a5f5a Merge pull request #1076 from philejmath/readme_updates
Updates Jupyter server config file names and locations
2017-04-13 07:17:07 -07:00
Philip Matheson
c1eb7618d6 Updates jupyter server config names and locations to use "jupyter" instead of "ipython" 2017-04-12 12:18:36 -04:00
Carol Willing
0ce0dfbc35 Add information about DockerHub to FAQ 2017-04-10 09:49:17 -07:00
Carol Willing
a555af428d Merge pull request #1068 from zonca/patch-1
[DOC] gallery deployments, improve UCSD
2017-04-08 09:39:11 -07:00
Min RK
b5666a45f6 prevent crash on first poll failure of Spawners
1. only poll if server might be running
2. catch and log failure to poll, treat it as not running to avoid Spawner bugs aborting Hub startup
2017-04-08 10:57:22 +02:00
Andrea Zonca
170f0f918f [DOC] gallery deployments, improve UCSD
added post titles and added one more post.
2017-04-07 21:49:01 -07:00
Min RK
a59b0af2b4 test auto_login redirects 2017-04-07 17:01:51 +02:00
Min RK
3cac9a2203 add path arg to public_url helper 2017-04-07 17:01:51 +02:00
Min RK
6b22f80ead Add Authenticator.auto_login
Simplifies login URL, handler login

- all login redirects go to `settings['login_url']`
- `login_url` is unconditionally `/hub/login`
- `/hub/login` renders form page or 'login with...' button
- enabling auto_login redirects from /hub/login to Authenticator.login_url()
2017-04-07 14:49:18 +02:00
Min RK
5f498ffaf3 Merge pull request #1062 from betatim/doc-fix
Fix missing space in header
2017-04-07 11:48:34 +02:00
Tim Head
258fe7b277 Fix missing space in header 2017-04-07 10:08:07 +02:00
Carol Willing
703ed7d21e Merge pull request #938 from minrk/oauth-provider
Make JupyterHub an OAuth provider
2017-04-06 06:57:55 -07:00
Min RK
9a1f84329f clarify oauth store docstrings
per review
2017-04-06 12:15:34 +02:00
Min RK
a20c7eb4de remove unused/unimplemented AccessTokenStore methods 2017-04-06 12:13:08 +02:00
Min RK
e866651f96 update admin access deprecation message 2017-04-06 11:59:31 +02:00
Min RK
2b5f42a546 docstring clarifying what we override in OAuthHandler 2017-04-06 11:50:23 +02:00
Min RK
b811c63ac5 blacklist sphinx 1.5.4
it has a bug preventing docs from building
2017-04-06 10:09:14 +02:00
Min RK
c7ea106675 use User wrappers in test_spawner 2017-04-05 16:12:29 +02:00
Min RK
1f2218c875 update travis.yml
- remove Python 3.3
- install node.js 6 with nvm
- remove use of outdated travis-wheels
2017-04-05 16:04:34 +02:00
Min RK
99369aa5a1 fix trailing - in oauth-client-id for single-user servers with empty server_name 2017-04-05 15:53:49 +02:00
Min RK
ffd3c171fe fix oauth url for SU servers with subdomains
and services without
2017-04-05 15:53:49 +02:00
Min RK
ce4b9e8e9f only store token in single-user cookie
not the user model

preserves cached-response behavior from the Hub
so that the Hub can still revoke tokens.
2017-04-05 15:53:49 +02:00
Min RK
ef51eb21e0 get OAuth working with subdomains
needs a lot of host passing around
2017-04-05 15:53:49 +02:00
Min RK
b1efe3a5c1 load initial API token before setting up oauth client 2017-04-05 15:53:48 +02:00
Min RK
6d647b5387 use API token for oauth client secret
rather than a separate single-purpose secret

since we need the token anyway, use it for the secret handshake as well
2017-04-05 15:53:48 +02:00
Min RK
d11c7ba4db cleanup more after mockservices 2017-04-05 15:53:48 +02:00
Carol Willing
6b33358c56 Merge pull request #1054 from parente/clarify-token-api-auth
Minor update to clarify hub token auth
2017-04-04 20:20:48 -07:00
Peter Parente
9030302ff7 Fix typo request -> requests 2017-04-04 22:36:05 -04:00
Peter Parente
1631a6eab0 Minor update to clarify hub token auth 2017-04-04 22:33:57 -04:00
Min RK
c6fe145030 s/JupyterHubOAuthCallback/HubOAuthCallback/ 2017-04-04 17:02:34 +02:00
Min RK
5b1435081a remove redundant/unused code in mockservice fixture 2017-04-04 17:02:34 +02:00
Min RK
39fce0304d support oauth in services
fix bugs caught by tests
2017-04-04 17:02:34 +02:00
Min RK
5a5fdc2565 validate oauth client_id/secret 2017-04-04 17:02:33 +02:00
Min RK
bef121dbe3 get default hub_prefix from env 2017-04-04 17:02:33 +02:00
Min RK
0b7a43f6fa remove placeholder oauth example 2017-04-04 14:26:44 +02:00
Peter Parente
2d1a45f019 Merge pull request #1050 from willingc/admin-doc
Clarify admin users and access in docs
2017-03-31 20:58:54 -04:00
Carol Willing
5494172706 Clarify admin users and access in docs 2017-03-31 10:28:37 -07:00
Min RK
198bb875df delay evaluation of oauth environment variables
only affects mocking in tests
2017-03-31 17:07:21 +02:00
Min RK
d1822ee939 handle hub prefix in HubAuth 2017-03-31 17:06:51 +02:00
Min RK
5e1516189b allow oauth provider to be missing
mostly for testing
2017-03-31 16:15:00 +02:00
Min RK
5819b442aa stop using deprecated server cookie in tests
use Hub cookie instead, which still exists
2017-03-31 15:58:39 +02:00
Min RK
4bb8e47f3b implement admin-access with OAuth 2017-03-30 19:15:43 +02:00
Min RK
ff6a68112e put whole user model in cookie
ensures cached value has all the info needed (group, etc.)
2017-03-30 16:52:20 +02:00
Min RK
52b9060415 remove debug-print in self handler 2017-03-30 16:35:50 +02:00
Min RK
74728e5f42 make HubOAuth a subclass
instead of implementing both shared-cookie and OAuth on HubAuth
2017-03-30 15:57:58 +02:00
Min RK
3e482d08d7 Don't overwrite class name when patching-in hub auth 2017-03-30 15:24:48 +02:00
Min RK
7e55220c3f use OAuth in single-user server 2017-03-30 15:24:35 +02:00
Min RK
453d1daf8b move oauth tables to top-level orm 2017-03-29 13:35:13 +02:00
Min RK
d0eb4e0946 add /api/user handler for identifying the requester 2017-03-28 16:19:56 +02:00
Min RK
9a40196678 Avoid storing secrets and tokens at rest
- OAuth access tokens *are* APITokens.
  oauth_access_tokens table only stores extra oauth metadata.
- only store hashed client_secret in database,
  using HashedCompare to allow comparison.
2017-03-28 16:19:56 +02:00
Min RK
4f7552ea1d OAuth works! 2017-03-28 16:19:56 +02:00
Min RK
7412e357cf allow 'bearer' in Authorization header
since that's what OAuth likes
2017-03-28 16:19:56 +02:00
Min RK
bac96c679f fix login URL for oauth provider 2017-03-28 16:19:56 +02:00
Min RK
4f1d201286 OAuth handlers inherit from BaseHandler 2017-03-28 16:19:56 +02:00
Min RK
bcf6559514 WIP: Make JupyterHub an OAuth provider 2017-03-28 16:19:55 +02:00
Min RK
0af9f2b875 Merge pull request #1046 from willingc/iss753
Add default behavior of whitelist to FAQ in docs
2017-03-28 09:31:06 +02:00
Min RK
d9393c6663 Merge pull request #1047 from willingc/iss1024
Add note to FAQ about updating node on Debian
2017-03-28 09:30:30 +02:00
Carol Willing
00274c991f Add note to FAQ about updating node on Debian 2017-03-27 08:51:20 -07:00
Carol Willing
e6848b68aa Add default behaviorof whitelist to doc FAQ 2017-03-27 07:27:46 -07:00
Carol Willing
853a460bd7 Merge pull request #1043 from minrk/local.jovyan
run subdomain test with localhost.jovyan.org
2017-03-27 06:48:46 -07:00
Carol Willing
ff5b708707 Merge pull request #1044 from minrk/hex-regex
match the whole content when checking if cookie secret is hex
2017-03-27 06:46:15 -07:00
Min RK
0d62ba2f80 use hex secretfile in tests 2017-03-27 14:02:30 +02:00
Min RK
f257716d1b match the whole content when checking if cookie secret is hex
fixes spurious message with base64 cookie secrets that start with hex subset
2017-03-27 14:02:30 +02:00
Min RK
43a6cd0bf9 Merge pull request #1039 from minrk/validate_security
prevent warnings about security in single-user servers
2017-03-27 13:58:14 +02:00
Min RK
af8965664e Merge pull request #1030 from yuvipanda/port-configurable
Tag c.Spawner.port as configurable
2017-03-27 13:39:07 +02:00
Min RK
168ad315c7 run subdomain test with localhost.jovyan
instead of relying on xip.io, which seems to be flaky sometimes
2017-03-27 12:48:10 +02:00
Min RK
66510de4e9 Merge pull request #1040 from willingc/doc-logging
Add rotating log info by @minrk to docs
2017-03-27 12:37:32 +02:00
Carol Willing
942e05888b Add rotating log info by @minrk to docs 2017-03-24 10:56:35 -07:00
Min RK
1970273c58 Merge pull request #1027 from mgeplf/form_redirect
Teach FormSpawner to handle query next=/path/to/landing
2017-03-24 15:56:58 +01:00
Min RK
06d081a73b prevent warnings about security in single-user servers
single-user warns if no token or password is set unless validate_security is overridden

these checks are not relevant when using JupyterHub
2017-03-24 13:14:18 +01:00
Min RK
352efa6d47 Merge pull request #1036 from yuvipanda/none-cmd
Allow setting spawner.cmd to None
2017-03-24 11:32:19 +01:00
Min RK
586dc3868d describe when setting port config makes sense
only in containers / remote servers
2017-03-24 11:14:18 +01:00
yuvipanda
0fe149dd57 Allow setting spawner.cmd to None
In some spawners you want to unset .cmd - for example, in
KubeSpawner setting it to None will use the CMD metadata that
is set in the Docker Image. Currently there's no way to set a
None value - you can't set it to [] either. Treating None and
empty values as separate is a useful thing to have.
2017-03-23 16:49:50 -07:00
yuvipanda
688845b907 Tag c.Spawner.port as configurable
Fixes #1029
2017-03-18 17:25:57 -07:00
Mike Gevaert
21af37a7a3 Teach FormSpawner to handle query next=/path/to/landing
* before, if /user-redirect/ was used, or if ?next=/path/
  and there was a FormSpawner, the query param would be lost
2017-03-17 14:00:15 +01:00
Carol Willing
6078b8d9e5 Merge pull request #1025 from barrachri/correct_named_servers
correct self.allow_multiple_servers to self.allow_named_servers
2017-03-16 18:30:17 -07:00
Christian Barra
bfe1457897 fix after test fail 2017-03-17 01:53:04 +01:00
Christian Barra
f873b77a5f correct self.allow_multiple_servers to self.allow_named_servers 2017-03-17 01:15:47 +01:00
Min RK
be1af58147 Merge pull request #1016 from yuvipanda/accessibility
Hide the logout icon from screen readers
2017-03-09 13:45:38 -08:00
Min RK
2b8268f1d4 Merge pull request #1015 from willingc/aws-config
[DOC] Integrate AWS example into doc
2017-03-09 13:44:44 -08:00
Min RK
6cc3cd325c Merge pull request #1014 from willingc/galler
[DOC] Add gallery of jupyterhub deployments
2017-03-09 13:44:19 -08:00
YuviPanda
efab0dbc47 Hide the logout icon from screen readers
This makes the logout link more discoverable by screen readers,
which sort links based on what they say. Since our icon was
in front of and not behind 'Logout', someone looking for Logout
will not find this
2017-03-09 10:35:28 -08:00
Carol Willing
a5b4ed83f7 Integrate AWS example into doc 2017-03-07 16:11:29 -08:00
Carol Willing
8eed5c7709 Merge pull request #1002 from ThomasMChen/aws-setup-doc
Add AWS setup documentation.
2017-03-07 16:00:24 -08:00
Carol Willing
883d3ad29b Fix typo 2017-03-07 15:55:03 -08:00
Carol Willing
044d5d2a84 Add gallery of deployments to docs 2017-03-07 15:51:52 -08:00
Min RK
68f23b2cdf Merge pull request #1009 from jupyterhub/willingc-patch-1
Add word to docstring to improve comprehension
2017-03-05 16:03:39 -08:00
Carol Willing
91553ebe34 Add word to docstring to improve comprehension 2017-03-05 13:15:58 -08:00
Carol Willing
a45bc9b31e Merge pull request #1008 from willingc/rtd-build
Pin Python to 3.5 for RTD build
2017-03-05 12:37:20 -08:00
Carol Willing
849f52de67 Pin Python to 3.5 2017-03-05 12:28:03 -08:00
Min RK
46f9841dce Merge pull request #1007 from barrachri/contributor_list
correct barrachri
2017-03-05 09:53:08 -08:00
Christian Barra
d8213b5fa5 correct barrachri 2017-03-05 12:35:26 +01:00
Carol Willing
ee276adcf8 Merge pull request #1006 from jupyterhub/willingc-patch-1
Add Christian Barra to contributor list
2017-03-04 15:28:46 -06:00
Carol Willing
07ae847d08 Add Christian Barra to contributor list 2017-03-04 15:28:05 -06:00
Min RK
95dc4713f4 Merge pull request #942 from barrachri/multi_servers
Multiple singleuser servers
2017-03-04 14:00:53 -05:00
Christian Barra
2294dc0ad9 from multiservers to namedservers 2017-03-03 03:42:24 +01:00
Min RK
87c0d7e54f Merge pull request #1005 from prasadkatti/patch-1
minor fix in upgrade process doc
2017-03-01 15:38:59 -05:00
Prasad Katti
18238241ef minor fix 2017-03-01 12:24:55 -08:00
Min RK
192cb193a1 Merge pull request #1003 from whitead/issue_997_fix
Ensure that SERVICE_FIX has trailing slash
2017-02-27 23:20:49 +01:00
Andrew White
2fb503df17 Ensure that SERVICE_FIX has trailing slash.
Fixes Issue #997. Also updated Traitlets to 4.3.2 since the change in singleuser.py relies on trait default values being checked through validator, which was added in traitlets 4.3.2.
2017-02-27 16:34:54 -05:00
Thomas Chen
810566729d Add AWS setup documentation. 2017-02-25 21:16:06 -06:00
Christian Barra
746912cece fix *args and **kwargs 2017-02-24 00:37:41 +01:00
Christian Barra
7a38a57397 remove unused imports and correct base_url 2017-02-24 00:37:41 +01:00
Christian Barra
4fdf405d77 add JupyterHub.allow_multiple_servers 2017-02-24 00:37:41 +01:00
Christian Barra
488706293f pass server_name to the spawner 2017-02-24 00:37:41 +01:00
Christian Barra
9373325f1b fix options error and base_url 2017-02-24 00:37:40 +01:00
Christian Barra
e151248ac2 fix server_name 2017-02-24 00:37:40 +01:00
Christian Barra
b09ccc4373 fix base_url 2017-02-24 00:37:40 +01:00
Christian Barra
f4a7e28aa5 add default_server_name, change spawn start 2017-02-24 00:37:40 +01:00
Christian Barra
5b85d1e248 correct server name and base_url unique=True 2017-02-24 00:09:48 +01:00
Christian Barra
a85bc5cad4 change classes for creating/deleting a server, add server_name param for delete method 2017-02-24 00:09:48 +01:00
Christian Barra
d682edd44f use only the first 10 chars of server_url 2017-02-24 00:09:48 +01:00
Christian Barra
3524399984 fix some errors 2017-02-24 00:09:48 +01:00
Christian Barra
b127788100 add a new base for multi servers 2017-02-24 00:09:48 +01:00
Christian Barra
a823a6b371 add a name field for the server 2017-02-24 00:09:48 +01:00
Carol Willing
b47f76c037 Merge pull request #983 from minrk/config-docs
add configurable traits to api docs
2017-02-22 08:36:33 -06:00
Min RK
1d19684b2c Handle traitlets 4.x 2017-02-21 18:06:48 +01:00
Min RK
08e8c93b16 add app.rst 2017-02-20 21:44:02 +01:00
Carol Willing
a0103ebd6c Merge pull request #988 from minrk/cookie-secret-256b
use 32B hex cookie secret
2017-02-17 11:38:09 -08:00
Carol Willing
b5a600d488 Merge pull request #984 from minrk/spawner-shell
allow customization of spawn command
2017-02-17 10:43:31 -08:00
Min RK
27410a6c51 remove spurious print 2017-02-15 11:31:25 +01:00
Min RK
67d6de9f68 don't forget to yield 2017-02-15 11:30:34 +01:00
Min RK
3996fa00ef turn off database echo in tests
it's a bunch of noise
2017-02-15 11:29:48 +01:00
Min RK
42f8509287 use observer instead of validator for checking cookie length
since we aren't mutating the value
2017-02-15 10:58:16 +01:00
Min RK
11b738b837 Merge pull request #989 from willingc/update-confpyapp
Rename to mocked_app to avoid shadowing app
2017-02-15 10:56:00 +01:00
Carol Willing
576858b6ca Rename to mocked_app to avoid shadowing app 2017-02-14 18:55:02 -08:00
Carol Willing
645c2bdd4a Merge pull request #974 from willingc/travis-config
Refactor travis config for more efficient builds
2017-02-14 18:18:51 -08:00
Min RK
9ae708b367 use 32B hex cookie secret
instead of large b64 secret, which doesn't make sense for sha256

Warn about deprecated base64 secrets and too-large secrets.
2017-02-14 14:36:50 +01:00
Min RK
abf554f9cf Merge pull request #987 from yuvipanda/cookie-id-nullcheck
Make cookie_id be unique and not-null too
2017-02-14 13:02:45 +01:00
YuviPanda
9df6e76cc3 Make cookie_id be unique and not-null too
Fixes #985
2017-02-13 09:15:39 -08:00
Min RK
7afbe952e6 test
take pytest-tornado for a spin

it's nice!
2017-02-13 17:55:50 +01:00
Min RK
00aa92f7b6 add env handler to mocksu 2017-02-13 17:53:30 +01:00
Min RK
4ae264de5e allow customization of spawn command
- add shell_cmd for launching with a shell (e.g. `bash -l -c`
- add popen_kwargs for overriding keyword args passed to Popen
2017-02-13 17:51:53 +01:00
Min RK
4b987dd334 add configurable traits to api docs 2017-02-13 14:18:20 +01:00
Carol Willing
f75c4c0ba3 Edit per @minrk review 2017-02-10 10:40:57 -08:00
Carol Willing
8b4d089376 Remove extra dash in maxfail 2017-02-10 10:40:57 -08:00
Carol Willing
bd2e758b04 Add maxfail to tests to prevent travis stalls 2017-02-10 10:40:57 -08:00
Carol Willing
54e5910e45 Remove verbose tests 2017-02-10 10:40:57 -08:00
Carol Willing
5460d5748f Remove travis retry 2017-02-10 10:40:57 -08:00
Carol Willing
25d5d95a5b Remove pypy test 2017-02-10 10:40:57 -08:00
Carol Willing
8db26af57a Update conditionals 2017-02-10 10:40:57 -08:00
Carol Willing
4f29cbe81f Update travis settings 2017-02-10 10:40:57 -08:00
Min RK
0dced91495 Merge pull request #975 from willingc/cleanup-fixtures
Remove deprecated yield_fixture
2017-02-10 10:04:30 +01:00
Min RK
c02a463348 Merge pull request #978 from willingc/style-util
Add flake8 support
2017-02-10 10:03:47 +01:00
Carol Willing
a2f717fba2 Remove pylintrc for a different PR 2017-02-09 08:03:58 -08:00
Carol Willing
8973571dc0 Add pylint config file 2017-02-09 07:38:36 -08:00
Carol Willing
0fe3aacb4d Update punctuation per @minrk 2017-02-09 06:48:15 -08:00
Carol Willing
7313b4fd26 Update ignored errors in flake8 config 2017-02-09 06:15:06 -08:00
Carol Willing
5c0b3f8b34 Add spacing for user.py 2017-02-08 22:36:56 -08:00
Carol Willing
a4eb795d32 Add exclude files to flake8 config 2017-02-08 22:33:58 -08:00
Carol Willing
8e1efc2851 Remove extra space in __init__.py 2017-02-08 22:33:13 -08:00
Carol Willing
8c999907c2 Add spacing to _data.py 2017-02-08 22:26:39 -08:00
Carol Willing
cd7a31dd3c Add spacing to app.py 2017-02-08 22:23:28 -08:00
Carol Willing
b21b0427d1 Add error to flake8 config 2017-02-08 22:22:59 -08:00
Carol Willing
3a2299f7f2 Add space to auth.py 2017-02-08 22:04:53 -08:00
Carol Willing
7d5287000f Fix spacing in dbutil.py 2017-02-08 22:03:56 -08:00
Carol Willing
bc37c56742 Add error to flake8 config 2017-02-08 22:03:33 -08:00
Carol Willing
97b04d8b43 Add spacing to emptyclass.py 2017-02-08 21:58:59 -08:00
Carol Willing
5de1c078d2 Edit spacing in log.py 2017-02-08 21:49:19 -08:00
Carol Willing
021ef6e6c4 Add error to flake8 config 2017-02-08 21:47:06 -08:00
Carol Willing
69d20eb297 Edit spacing in orm.py 2017-02-08 21:46:33 -08:00
Carol Willing
4688348020 Edit spacing in singleuser.py 2017-02-08 21:38:23 -08:00
Carol Willing
cf02f3133a Correct spacing in spawner.py 2017-02-08 21:29:56 -08:00
Carol Willing
e0748540d7 Ignore errors in flake8 config 2017-02-08 21:29:35 -08:00
Carol Willing
ab3c28e46a Correct spacing in traitlets.py 2017-02-08 21:19:55 -08:00
Carol Willing
13ae12b57d Correct style spacing 2017-02-08 21:18:12 -08:00
Carol Willing
222cdc7f79 Add config file for flake8 2017-02-08 21:17:46 -08:00
Carol Willing
e8a1d2f1bd Clean up docstring errors 2017-02-08 20:53:53 -08:00
Carol Willing
5245670af1 Remove deprecated yield_fixture; add docstrings 2017-02-08 14:16:36 -08:00
Carol Willing
6b83d516a7 Merge pull request #976 from minrk/no-token-pop
Don't pop token env in single-user servers
2017-02-08 14:03:02 -08:00
Carol Willing
b72562e805 Merge pull request #971 from minrk/token-page
Add page for requesting tokens
2017-02-08 13:57:45 -08:00
Min RK
0b964c8358 Don't pop token env in single-user servers
Users should be allowed to access their own tokens to talk to the Hub API.
2017-02-08 22:31:18 +01:00
Min RK
d61f9547fe Merge pull request #973 from apetresc/patch-1
Update traitlets dependency to 4.3
2017-02-08 22:24:25 +01:00
Adrian Petrescu
78360608b1 Update traitlets dependency
Fixes #972. Currently, Jupyterhub actually has a hard requirement on the 4.3 traitlets API, otherwise you'll run into the crash described in that issue for any traitlets version older than that.
2017-02-08 11:21:23 -05:00
Min RK
2a25e3cb89 replace existing get_token tests 2017-02-08 16:46:50 +01:00
Min RK
f3b7fda4a8 it's JupyterHub
not Jupyter Hub
2017-02-08 14:43:11 +01:00
Min RK
6c6d070b16 minor html cleanup 2017-02-08 14:42:41 +01:00
Min RK
eec0a11ef0 add POST /authorizations/token to rest API docs 2017-02-08 14:39:13 +01:00
Min RK
2b262f453d test requesting token via API 2017-02-08 14:32:19 +01:00
Min RK
c2b494f702 put nav in the header
reduce custom css, use more bootstrap variables.

Admin link is now in the heading rather than the list of big buttons
2017-02-08 14:19:35 +01:00
Min RK
958ee00efd Add /token page with a button for requesting new tokens 2017-02-08 14:16:11 +01:00
Min RK
363354d941 allow POST /authorizations/token to request new tokens 2017-02-08 13:39:46 +01:00
Carol Willing
074ea61514 Merge pull request #969 from minrk/logout-redirect
redirect to `/hub/login` to avoid automatically starting login process
2017-02-03 08:17:19 -08:00
Min RK
abc59d3d30 redirect logout page to login page directly
instead of relying on root redirect
2017-02-03 12:55:45 +01:00
Min RK
fea683f992 redirect root to /hub/login instead of authenticator.login_url
/hub/login always renders a page,
whereas `authenticator.login_url` may automatically log the user in via redirects,
causing logout to appear not to work, as redirects immediately cause login again.
2017-02-03 12:51:03 +01:00
Min RK
3402f4f514 Merge pull request #966 from minrk/service-token-auth
support service tokens in HubAuth
2017-02-01 13:11:32 +01:00
Carol Willing
3bb82ea330 Merge pull request #949 from willingc/test-mock
Refactor test classes used to mock services
2017-01-27 05:43:29 -08:00
Carol Willing
bced09e5b3 Add file docstring from @minrk 2017-01-27 05:19:05 -08:00
Carol Willing
9e84402f42 Edit docstrings to clarify handlers are not mocked 2017-01-27 04:58:29 -08:00
Min RK
18c65453fd Merge pull request #965 from willingc/test-proxy
Refactor proxy tests
2017-01-27 13:40:28 +01:00
Carol Willing
57ed99020f Edit comment 2017-01-27 04:19:43 -08:00
Carol Willing
caa3b0c438 Parameterize test values 2017-01-27 04:14:51 -08:00
Carol Willing
5133cf0275 Add some comments 2017-01-27 04:14:51 -08:00
Carol Willing
7f6c080b46 Fix pep8 errors 2017-01-27 04:14:51 -08:00
Carol Willing
142907395f Use pytest parameterize for proxy tests; fix spacing 2017-01-27 04:14:51 -08:00
Min RK
43d069438e Merge pull request #956 from willingc/test-api
Refactor API tests
2017-01-27 10:36:14 +01:00
Carol Willing
e7b73c4f53 Add docstrings and remove request_received 2017-01-26 13:58:38 -08:00
Carol Willing
f2ca0a2372 Implement all methods for classes that inherit from abstract class 2017-01-26 12:54:11 -08:00
Carol Willing
021cfe446f Fix formatting on a few requests 2017-01-26 12:41:39 -08:00
Carol Willing
1a71c906d5 Revert "Relax line length for requests" 2017-01-26 12:26:02 -08:00
Carol Willing
10d2eb6449 Return to original style for line length for requests 2017-01-26 12:20:19 -08:00
Carol Willing
0f283e088e Fix minor formatting 2017-01-26 12:17:11 -08:00
Carol Willing
025977f19a Clean up vertical spacing 2017-01-26 12:17:11 -08:00
Min RK
2a9ba788d0 shorten date_fmt in tests
reduces log prefix length a bit in test output
2017-01-26 11:52:59 +01:00
Min RK
aa65266726 support services in HubAuth 2017-01-26 11:52:40 +01:00
Min RK
4b6c58292b add 'kind' field to user and group models 2017-01-26 11:48:20 +01:00
Min RK
d0813cc736 support service tokens in /api/authorizations 2017-01-26 10:44:25 +01:00
Min RK
f1d7e5e779 Merge pull request #961 from minrk/get-user-simplified
Enable token authentication in HubAuth
2017-01-26 09:55:35 +01:00
Min RK
66f01fc880 set login url on hub_auth 2017-01-25 22:58:10 +01:00
Min RK
d93384536f clarify some things
- cleanup docstrings
- more comments
- rename cookie_cache to cache, since it's not a cache of cookies
2017-01-25 17:10:14 +01:00
Min RK
69250db70e support token authentication in HubAuth.get_user
in Authorization header or `?token` parameter

enables token authentication in single-user server based on notebook >= 4.3 as well
2017-01-25 13:53:36 +01:00
Min RK
ad52398087 add get_login_url to HubAuthenticated
needed for tornado's default redirect
2017-01-25 13:52:14 +01:00
Min RK
4f1eec31a1 more code consolidation in HubAuth
consolidates duplicate code in user_for_cookie and user_for_token
into _check_hub_authorization
2017-01-25 13:50:20 +01:00
Min RK
43c02740ab Merge pull request #960 from DeepHorizons/get_user_by_token
Added user_for_token method, moved r check into its own function
2017-01-25 10:39:01 +01:00
Joshua Milas
4605f74cf9 Fixed missing variable 2017-01-24 11:49:18 -05:00
Joshua Milas
9ab4b35f22 Changed error message to be more generic 2017-01-24 11:47:52 -05:00
Min RK
e9784f0e69 Merge pull request #959 from willingc/test-typo
Add missing assert to test
2017-01-24 13:27:51 +01:00
Min RK
3e37d0a39b Merge pull request #958 from willingc/add-badges
Edit README content and update formatting
2017-01-24 13:14:57 +01:00
Min RK
44ae162f09 Merge pull request #955 from willingc/test-services
Refactor services tests
2017-01-24 13:13:15 +01:00
Joshua Milas
2821b9a832 Added user_for_token method, moved r check into its own function 2017-01-23 21:12:40 -05:00
Carol Willing
cf97247f75 Add missing assert to test 2017-01-23 08:33:48 -08:00
Carol Willing
1bb40e2be1 Add built-in spawner to table 2017-01-23 08:09:00 -08:00
Carol Willing
869db9e31c Edit content and update formatting 2017-01-22 21:00:58 -08:00
Carol Willing
39ee52ad3c Refactor services tests 2017-01-20 23:13:09 -08:00
Carol Willing
7e699af2b5 Merge pull request #953 from willingc/covfix
Rename test class to stub class to allow pytest collection

Closes #952
2017-01-20 14:52:39 -08:00
Min RK
2b344cc717 Merge pull request #950 from willingc/travis36
Add Python versions to Travis
2017-01-20 11:25:17 -10:00
Carol Willing
246f0bc442 Omit alembic directory from report 2017-01-20 12:30:46 -08:00
Carol Willing
4afb659f44 Omit travis site-packages directory from report 2017-01-20 12:25:33 -08:00
Carol Willing
a43069fc35 Correct syntax in coverage command 2017-01-20 11:35:39 -08:00
Carol Willing
5b43266278 Update coverage setting to ignore test directory 2017-01-20 11:26:19 -08:00
Carol Willing
5df16371e1 Rename class used in test cases to StubSingleUserSpawner 2017-01-20 10:49:59 -08:00
Carol Willing
c086f05c7c Rename test class to allow pytest to collect tests 2017-01-20 10:49:59 -08:00
Carol Willing
7a38857bcd Add Python versions to Travis 2017-01-20 08:32:52 -08:00
Min RK
e860925f57 Merge pull request #944 from barrachri/fix_patch_post_#941
check name collisions on rename
2017-01-19 10:38:38 -10:00
Christian Barra
3808067dd7 better docs 2017-01-19 10:57:18 +01:00
Min RK
c7d7dec40d Merge pull request #939 from minrk/service-logs
more debugging and health checks for services
2017-01-18 16:19:01 -10:00
Christian Barra
e96e0acc9f more pythonic 2017-01-19 03:05:28 +01:00
Min RK
3efd2398ca review comments 2017-01-18 16:03:05 -10:00
Christian Barra
7284ef6e06 change from username to name 2017-01-19 02:35:42 +01:00
Christian Barra
f5dc3ad753 fix to have unique username value 2017-01-19 02:30:04 +01:00
Christian Barra
fc0d0031bf typo correct 2017-01-16 17:03:47 +01:00
Min RK
d44ee4b8fa Merge pull request #937 from minrk/service-chdir
Don't set cwd to user's home for services
2017-01-16 15:39:20 +01:00
Min RK
eb5e755aa6 more debugging and health checks for services
- log that external services are added (helps catch accidental external services due to missing fields)
- check connectivity of services with web endpoints periodically
2017-01-16 15:36:11 +01:00
Min RK
6fc9e90f28 Don't set cwd to user's home for services
allow `cwd` setting to take effect
2017-01-15 20:10:06 +01:00
Min RK
2effd3da16 Merge pull request #933 from DeepHorizons/fix_service_help
Fixed help and documentation related to service tokens
2017-01-15 20:08:41 +01:00
Min RK
69230b1147 Merge pull request #936 from barrachri/add_grant_cookie_admin_services
Allow services to request admin-access
2017-01-15 20:08:06 +01:00
Christian Barra
5435bf3ec4 add api_token to services' properties 2017-01-15 13:36:36 +01:00
Christian Barra
b0b13bfcb9 fix AttributeError when a service ask for a cookie 2017-01-14 05:48:07 +01:00
Joshua Milas
c3b0b2ecf0 Fixed help and documentation related to service tokens
The documentation stated that the key `token` should be used to specify
the pregenerated token in `JupyterHub.services`. This is wrong as the key
should be `api_token`.

This changes the help on the trait, along with changing the module
docstring in `service.py`.
2017-01-13 17:45:42 -05:00
Min RK
a276421d25 Merge pull request #907 from barrachri/adding_multi_server_features_orm
Allow users to have multiple servers (in db)
2017-01-11 15:19:47 +01:00
Christian Barra
dbb6303bdc update and test with version 0.7.2 2017-01-11 14:02:11 +01:00
Christian Barra
d28036e173 fix docstrings 2017-01-11 12:27:30 +01:00
Carol Willing
bc3f1cae16 Merge pull request #931 from jupyterhub/willingc-patch-1
Correct links for changelog
2017-01-10 07:38:09 -08:00
Carol Willing
5e84d0c2b3 Correct links for changelog
Update links for 0.7.2 and Unreleased titles
2017-01-10 07:23:39 -08:00
Min RK
086f88852d back to dev 2017-01-10 16:15:01 +01:00
Min RK
aa132cade7 release 0.7.2 2017-01-10 16:12:45 +01:00
Carol Willing
dd35ffbe86 Merge pull request #928 from minrk/0.7.2
Changelog for 0.7.2
2017-01-09 16:18:12 -08:00
Min RK
8edcf8be81 Changelog for 0.7.2 2017-01-09 12:45:16 +01:00
Christian Barra
11196443ac remove relationship, fix some typo 2017-01-06 22:15:51 +01:00
Min RK
29b02b7bcb Merge pull request #927 from willingc/clarify-whitelist
Add better prose for removing users
2017-01-06 20:25:01 +01:00
Carol Willing
0383bc27b2 Add better prose for removing users 2017-01-06 08:52:48 -08:00
Carol Willing
65d5102b49 Merge pull request #926 from minrk/singleuser-service-defaults
support service env vars in singleuser entrypoint
2017-01-06 08:28:48 -08:00
Min RK
8a226e6f46 simplify singleuser-service examples
now that service env vars are respected
2017-01-06 17:21:28 +01:00
Min RK
0bd34e0a10 support service env variables in singleuser
and set a few sensible defaults where they are known/likely
2017-01-06 17:21:10 +01:00
Min RK
186107d959 cache HubAuth user per request 2017-01-06 17:19:10 +01:00
Carol Willing
91b07b7ea4 Merge pull request #924 from minrk/singleuser-service-example
singleuser-server service example
2017-01-06 08:10:34 -08:00
Min RK
f5b30fd2b4 move version requirement further up 2017-01-06 16:57:13 +01:00
Min RK
0234396c2c Merge pull request #922 from yuvipanda/fix-user-redirect
Pass query params through with user-redirect
2017-01-06 13:31:23 +01:00
Min RK
a43d677ae4 add external-service shared notebook example 2017-01-06 13:30:53 +01:00
Min RK
dcfe71e7f0 add managed notebook service example 2017-01-06 13:30:53 +01:00
Min RK
5d41376c2e use JUPYTERHUB_API_TOKEN env in Spawner
to be more consistent with services

deprecate JPY_API_TOKEN, but keep it around for compatibility
2017-01-06 13:30:53 +01:00
Min RK
dd083359ec Merge pull request #925 from minrk/fix-hub-group-auth
[HubAuth] Fix group authentication for services
2017-01-06 13:30:30 +01:00
Min RK
e6d54960ba test group whitelist checking 2017-01-06 13:24:40 +01:00
Min RK
a9295bc5c2 more debug logging for Hub auth 2017-01-06 13:24:40 +01:00
Min RK
2015c701fa HubAuth services: fix group authentication checking
If group authentication checking was enabled, any user would be allowed
2017-01-06 13:24:40 +01:00
YuviPanda
3e9c18f50a Pass query params through with user-redirect 2017-01-05 17:18:36 -08:00
Min RK
7cac874afc Merge pull request #919 from ellisonbg/nbserver-group
Adding group to single user server for group based auth
2017-01-05 14:37:20 +01:00
Brian E. Granger
a7b6bd8d32 Adding group to single user server for group based auth 2017-01-04 20:12:34 -07:00
Min RK
1649a98656 2017 typo 2017-01-03 15:55:39 +01:00
Christian Barra
6694cb42c8 remove pep8 corrections 2017-01-03 14:30:36 +01:00
Christian Barra
b6e293c38e update to the last jupyterhub version 2017-01-03 14:22:12 +01:00
Christian Barra
02090c953b fix errors, remove pep8 corrections 2017-01-03 14:10:46 +01:00
Min RK
ecbe51f60f signaling typo 2017-01-02 14:50:10 +01:00
Min RK
fed14abed3 back to dev 2017-01-02 14:44:07 +01:00
Min RK
94978ea9e0 release 0.7.1 2017-01-02 13:53:43 +01:00
Min RK
bf6999e439 changelog for 0.7.1 2017-01-02 13:53:43 +01:00
Carol Willing
020ee7378f Merge pull request #916 from rachmaninovquartet/master
Added Toree troubleshooting to docs
2016-12-22 13:56:51 -08:00
Min RK
e4a0569961 Merge pull request #915 from jupyterhub/willingc-patch-1
Update README to clarify docker image contents
2016-12-22 16:43:02 +01:00
Ian Maloney
4ff525d5bd updated docs/source/troubleshooting.md per conversation with @willingc in issue 889 2016-12-21 15:21:50 -05:00
Carol Willing
37a31b01b2 Update README to clarify docker image contents
Addresses #879 and #772 re: confusion about the docker image contents
2016-12-21 10:46:30 -08:00
Carol Willing
1604cb1b0b Merge pull request #914 from minrk/update-bootprint
fix rest-api doc building
2016-12-21 10:29:08 -08:00
Min RK
45702ac18c update bootprint to 0.10
0.8 has stopped working for some reason
2016-12-21 14:51:12 +01:00
Min RK
c81e9d60e4 fix rest-api link
link to REST API, not Python API
2016-12-21 14:51:12 +01:00
Carol Willing
224865b894 Merge pull request #910 from minrk/cleanup-server-token
Avoid cleaning up API tokens for Spawners that will resume
2016-12-20 08:29:06 -08:00
Min RK
3b3bc8224b comment review 2016-12-20 16:41:26 +01:00
Carol Willing
c56dc2ea6f Merge pull request #911 from jjaraalm/master
Update Service Docs

Closes #908
2016-12-19 10:28:30 -08:00
jjaraalm
62202bbb74 Revert "Revert "Update service docs""
This reverts commit 7ba28c0207.
2016-12-19 13:00:48 -05:00
jjaraalm
7ba28c0207 Revert "Update service docs"
This reverts commit 9392a29dad.
2016-12-19 12:59:42 -05:00
jjaraalm
9392a29dad Update service docs
Fixes #908
2016-12-19 12:56:26 -05:00
Min RK
72ab8f99ec Avoid cleaning up API tokens for Spawners that will resume
in which case the previous API token should be left alone.
2016-12-19 10:50:25 +01:00
Min RK
fcf32c7e50 Merge pull request #909 from willingc/update-travis
Add 3.6 to travis
2016-12-19 09:59:47 +01:00
Carol Willing
da451d6552 Add 3.6 to travis 2016-12-18 21:26:52 -08:00
Christian Barra
dbe8bf5428 add users_servers class in orm.py, correct test_orm.py, fix some pep8, issue #766 2016-12-17 04:55:00 +01:00
Carol Willing
662b1a4d4a Merge pull request #902 from minrk/redirect-empty-msg
Don't warn about empty next_url
2016-12-09 08:04:56 -08:00
Min RK
732adea997 Don't warn about empty next_url
empty next_url is fine
2016-12-09 15:34:32 +01:00
Carol Willing
7e1dbf3515 Merge pull request #896 from minrk/whitelist-warning
Warn about single-character names in whitelist
2016-12-05 11:16:30 -06:00
Min RK
65b92ec246 Warn about single-character names in whitelist
likely cause is `set('string')` typo instead of `set(['string'])`,
so include that in the error message:

    whitelist contains single-character names: ['i', 'k', 'm', 'n', 'r']; did you mean set(['ikmnr']) instead of set('ikmnr')?
2016-12-05 09:46:52 +01:00
Min RK
dc42ee4779 typo in changelog link 2016-12-02 18:12:28 +01:00
Min RK
c04441c1b2 back to dev 2016-12-02 18:08:03 +01:00
Min RK
c3faef8e2a release 0.7.0 2016-12-02 18:02:20 +01:00
Carol Willing
d2175635af Merge pull request #895 from minrk/release-0.7
Update changelog for 0.7 final
2016-12-02 10:47:21 -06:00
Min RK
1f7401cd14 Update changelog for 0.7 final 2016-12-02 17:35:19 +01:00
Min RK
c94b3e34d2 Merge pull request #894 from minrk/disable-token
disable unused token on singleuser-server
2016-12-02 17:01:50 +01:00
Carol Willing
566e1d05ea Merge pull request #893 from minrk/expanduser
call expanduser on singleuser notebook_dir
2016-12-01 21:53:24 -06:00
Min RK
0488d0bd73 call expanduser on singleuser notebook_dir
This copies validate_notebook_dir from notebook with one addition:
calling expanduser.
2016-12-01 22:04:18 +01:00
Min RK
ca31d9b426 disable token on singleuser-server
fixes confusing output about token access in notebook server startup
2016-12-01 21:59:44 +01:00
Min RK
8721f9010f Merge pull request #892 from yuvipanda/maybe-async
Document that authenticator's add_user maybe a coroutine
2016-12-01 17:58:02 +01:00
YuviPanda
88de48ebac Document that authenticator's add_user maybe a coroutine 2016-12-01 19:31:23 +05:30
Min RK
d5a6e2b2ac Merge pull request #886 from yuvipanda/spawner-docs 2016-11-30 13:48:05 +01:00
Min RK
2152a94156 review pass on spawner docstring changes
- small wording, spelling tweaks
- rst formatting fixes
- remove some spurious, cluttering newlines
- clearer traitlets default values on first line
2016-11-30 13:43:59 +01:00
Min RK
bc3824e9bf review pass on auth docstrings 2016-11-30 13:22:07 +01:00
YuviPanda
60bc92cf78 Spawner doc fixes per @willingc 2016-11-30 14:02:02 +05:30
YuviPanda
3b15467738 Clearer module docstring for spawner.py 2016-11-29 16:26:34 +08:00
YuviPanda
4970fe0a1c Add more docs for spawner base class 2016-11-29 16:25:15 +08:00
YuviPanda
7dbe2425b8 Fix typo 2016-11-29 16:00:25 +08:00
YuviPanda
433d44a642 Add docs for PAMAuthenticator 2016-11-29 15:58:35 +08:00
YuviPanda
7733d320d0 Add more docs to LocalAuthenticator 2016-11-29 15:56:16 +08:00
YuviPanda
20d367c2a8 Add more docs for authenticator base class 2016-11-29 15:55:32 +08:00
YuviPanda
4687fbe075 Add extended docs for LocalProcessSpawner too 2016-11-28 23:07:54 -08:00
YuviPanda
b0dc52781e Add info about shell expansion to cmd / args traitlets
We should probably standardize this too
2016-11-28 22:45:06 -08:00
YuviPanda
4f1f7d6b8f Add example use for default_url traitlet 2016-11-28 22:42:10 -08:00
YuviPanda
41f8608f4e Fix port config documentation to match reality 2016-11-28 22:41:47 -08:00
Min RK
ba3a8f2e76 Merge pull request #887 from yuvipanda/rename-spec
Rename MemorySpecification to ByteSpecification
2016-11-28 10:27:41 +01:00
YuviPanda
12e3a5496d Rename MemorySpecification to ByteSpecification 2016-11-27 17:57:34 -08:00
YuviPanda
280644bab5 Expand traitlet documentation for spawner base class 2016-11-27 17:53:41 -08:00
Carol Willing
bf28371356 Merge pull request #882 from minrk/alembic.ini
add alembic.ini to package_data
2016-11-22 08:10:43 -08:00
Carol Willing
ce237181f2 Merge pull request #881 from minrk/more-allow-async-whitelist
handle async check_whitelist in app
2016-11-22 07:46:27 -08:00
Min RK
85ca5a052e add alembic.ini to package_data 2016-11-22 16:21:03 +01:00
Min RK
db8b3dbce9 handle async check_whitelist in app
follow-up to previous PR
2016-11-22 16:06:08 +01:00
Min RK
9c2d56f015 Merge pull request #876 from jbweston/bugfix/whitelist-coroutine
allow `check_whitelist` to be a coroutine
2016-11-22 09:56:28 +01:00
Joseph Weston
d244a1e02f allow check_whitelist to be a coroutine
Some authenticators may have whitelist checking that requires
async operations.
2016-11-21 16:14:02 +01:00
Min RK
9f134277a9 Merge pull request #872 from jupyterhub/willingc-patch-1
Change py.test to newer convention of pytest
2016-11-16 10:18:15 +01:00
Carol Willing
ef9aca7bcb Change py.test to newer convention of pytest 2016-11-15 14:13:03 -08:00
Min RK
32f39f23eb Merge pull request #871 from jupyterhub/willingc-patch-1
Add info on tests to README
2016-11-15 20:39:59 +01:00
Carol Willing
c9b2beb821 Add info on tests to README 2016-11-15 06:35:39 -08:00
Min RK
e9ad82e350 release 0.7b1 2016-11-12 18:36:36 -08:00
Min RK
347dd3cc0f prune docs/node_modules 2016-11-12 18:36:30 -08:00
Min RK
798346dbe8 Merge pull request #869 from willingc/doc-service
Edit Services doc content
2016-11-12 18:28:24 -08:00
Carol Willing
fd94c6de17 Fix missing link target 2016-11-12 18:16:59 -08:00
Carol Willing
3fc6fc32c5 Add review comment by @parente 2016-11-12 18:07:17 -08:00
Carol Willing
a1b6aa5537 Add troubleshooting commands 2016-11-12 18:01:53 -08:00
Carol Willing
f9965bb3c3 Add example of Service per @parente 2016-11-12 17:37:30 -08:00
Carol Willing
541997371c Fix broken or changed links 2016-11-12 17:17:00 -08:00
Carol Willing
522c3e5bee Edit Services doc content 2016-11-12 16:54:57 -08:00
Carol Willing
1baf434695 Merge pull request #868 from minrk/more-changes
Add a few more things in the changelog
2016-11-12 13:40:16 -08:00
Carol Willing
92db71f293 Merge pull request #867 from minrk/upgrade-db-backup
backup db file during upgrade-db
2016-11-12 13:39:39 -08:00
Min RK
b985f8384d Add a few more things in the changelog 2016-11-12 12:54:44 -08:00
Min RK
4c2d049e70 backup db file during upgrade-db 2016-11-12 12:44:59 -08:00
Carol Willing
605c4f121c Merge pull request #866 from parente/note-about-db-secrets
Add two short notes about db security
2016-11-12 12:03:21 -08:00
Peter Parente
4baf5035cb Reflow markdown for easier editing 2016-11-12 11:57:45 -08:00
Peter Parente
f8a57eb7d9 Add two short notes about db security 2016-11-12 11:49:17 -08:00
Min RK
93ac343493 Merge pull request #865 from willingc/doc-tidbits
Add documentation prior to 0.7 beta
2016-11-12 11:40:53 -08:00
Carol Willing
dc092186f0 Edit example for clarity 2016-11-12 11:27:36 -08:00
Carol Willing
6b7c319351 Add intro and standardize code format 2016-11-12 11:15:44 -08:00
Carol Willing
ef5885f769 Make minor edits 2016-11-12 11:15:02 -08:00
Peter Parente
0ffd53424d Merge pull request #861 from willingc/issuetempl
Add initial issue template
2016-11-11 13:36:11 -08:00
Carol Willing
5f464d01b4 Soften tone 2016-11-11 10:44:20 -08:00
Yuvi Panda
0a054cc651 Merge pull request #858 from willingc/post855-edits
Reflow text and minor edits following PR #855
2016-11-11 09:54:14 -08:00
Carol Willing
348af48d45 Merge pull request #863 from minrk/checklist-checklist
Make the release checklist a GFM checklist
2016-11-11 09:31:47 -08:00
Min RK
4d03c00dab Make the release checklist a GFM checklist
so we can paste into a new issue when preparing for a release
2016-11-11 09:14:07 -08:00
Min RK
7a71074a55 Merge pull request #860 from willingc/release-checklist
Add a high-level release checklist
2016-11-11 08:23:12 -08:00
Carol Willing
5527a3e7dd Fix spacing 2016-11-11 07:39:23 -08:00
Carol Willing
f961800fa4 Add troubleshoot command per @parente review 2016-11-11 07:37:43 -08:00
Peter Parente
adbf961433 Merge pull request #859 from willingc/contrib-thanks
Update contributor thank you list
2016-11-11 07:30:02 -08:00
Carol Willing
73e130cb2c Add initial issue template 2016-11-11 07:03:05 -08:00
Carol Willing
a44f178b64 Fix typo 2016-11-11 03:56:42 -08:00
Carol Willing
057fe32e3b Add release checklist 2016-11-11 03:54:33 -08:00
Carol Willing
cad9ffa453 Update contributor thank you list 2016-11-11 03:29:42 -08:00
Carol Willing
a11193a240 Reflow text and minor edits 2016-11-11 03:13:51 -08:00
Carol Willing
ea61a580b3 Merge pull request #855 from yuvipanda/limits-env
Add docs for the LIMIT_ and GUARANTEE_ conventions
2016-11-11 02:43:05 -08:00
Min RK
0bf6db92dd typo in example 2016-11-10 17:07:48 -08:00
YuviPanda
b0f38e7626 Fix docs to match reality 2016-11-10 14:38:09 -08:00
YuviPanda
0f237f28e7 Rename the env variables
Match the traitlet names
2016-11-10 14:37:50 -08:00
YuviPanda
d63bd944ac Add clarifying comment about limit / guarantee env variables 2016-11-10 10:39:44 -08:00
YuviPanda
54e28d759d Some inline doc fixups 2016-11-10 10:31:04 -08:00
YuviPanda
a00c13ba67 Set allow_none=True for limit/guarantee floats 2016-11-09 09:41:54 -08:00
YuviPanda
b4bc5437dd Set allow_none = True as default for MemorySpecification 2016-11-08 22:43:47 -08:00
Min RK
13bc0397f6 Merge pull request #767 from willingc/upgrade723
Add document on upgrading JupyterHub and its db
2016-11-08 18:13:27 -08:00
YuviPanda
9eb30f6ff6 Add resource limits / guarantees consistently to jupyterhub
- Allows us to standardize this on the spawner base class,
  so there's a consistent interface for different spawners
  to implement this.
- Specify the supported suffixes and various units we accept
  for memory and cpu units.
- Standardize the way we expose resource limit / guarantees
  to single-user servers
2016-11-08 17:17:10 -08:00
YuviPanda
17f20d8593 Add docs for the LIMIT_ and GUARANTEE_ conventions
https://github.com/jupyterhub/jupyterhub/issues/854 has
rationale for why, and links to PRs.
2016-11-08 16:19:25 -08:00
Carol Willing
cd23e086a8 Add an upgrade checklist 2016-11-08 12:04:57 -08:00
Carol Willing
03087f20fe Add additional database content from @minrk review 2016-11-08 11:51:42 -08:00
Carol Willing
f536eb4629 Change title 2016-11-08 10:50:49 -08:00
Carol Willing
f3e814aa8a Minor edits 2016-11-08 10:50:49 -08:00
Carol Willing
5fb0a6dffe Add note on databases 2016-11-08 10:50:49 -08:00
Carol Willing
c7ba86d1d8 Add upgrade instructions 2016-11-08 10:50:49 -08:00
Carol Willing
38dcc694b7 Add shutdown and upgrade steps 2016-11-08 10:50:49 -08:00
Carol Willing
fdfffefefa Update process steps 2016-11-08 10:50:49 -08:00
Carol Willing
4e7704afd9 Edit heading levels 2016-11-08 10:50:49 -08:00
Carol Willing
b52fcf4936 Add structure to upgrading doc 2016-11-08 10:50:49 -08:00
Carol Willing
539be2f08e Add basics for alembic 2016-11-08 10:50:49 -08:00
Carol Willing
29b2836c50 Add wip upgrade doc 2016-11-08 10:50:49 -08:00
Min RK
3a757d003a Merge pull request #852 from parente/use-conda-forge
[WIP] Update Dockerfile
2016-11-08 09:58:36 -08:00
Peter Parente
236802be1f Update Dockerfile
* Use nodejs, CHP from condaforge
* Bump the version of conda used
2016-11-07 18:46:04 -08:00
Carol Willing
4a2c9e97c6 Merge pull request #844 from willingc/secure-doc
Reflow text in websecurity doc
2016-11-01 15:15:16 -07:00
Carol Willing
0444d8465c Reflow text in doc 2016-11-01 14:27:49 -07:00
Carol Willing
faef34e4ff Merge pull request #838 from minrk/ensure-strings
quotes around single-user CLI args
2016-11-01 14:05:56 -07:00
Carol Willing
c174ec42f0 Merge pull request #842 from minrk/generate-path-error
finish error message when generate-config path does not exist
2016-11-01 09:26:52 -07:00
Min RK
d484728de9 check directory existence when writing config file
rather than file

and put output on stderr with exit message
2016-11-01 14:47:44 +01:00
Min RK
7da7f7e074 quotes around single-user CLI args
avoids mishandling things such as integer-literals
2016-11-01 12:07:25 +01:00
Min RK
53bdcd7d74 Merge pull request #840 from parente/clear-services-cookie
Fix jupyter-services cookie reset on logout
2016-10-31 13:25:43 +01:00
Peter Parente
1849964699 Fix jupyter-services cookie reset on logout
It currently remains set after logout from the hub allowing the user to
continue to access any services.
2016-10-30 22:36:31 -04:00
Carol Willing
5163c7a97f Merge pull request #824 from minrk/allow-empty-state
Don't assume empty state means not running
2016-10-27 08:33:54 -07:00
Min RK
b9daef9947 docstring review 2016-10-27 11:41:23 +02:00
Carol Willing
f16e0488ab Merge pull request #837 from Scrypy/issue-821
Updated authenticators and spawner docs
2016-10-26 15:44:09 -07:00
Daniel Martinez
adc16be4dc Updated spawners docs 2016-10-26 16:50:25 -05:00
Daniel Martinez
3e4b4149de Updated authenticators docs 2016-10-26 16:48:15 -05:00
Min RK
c392bae7e4 Merge pull request #835 from willingc/check-return
Edit model check to be consistent for user and group
2016-10-26 23:25:24 +02:00
Carol Willing
2e5373aa37 Edit model check to be consistent for user and group 2016-10-26 12:03:53 -07:00
Min RK
5412cd414f Merge pull request #832 from willingc/replace-warn
Use warning instead of warn for logs
2016-10-26 13:26:41 +02:00
Carol Willing
d957c5158f Use warning instead of warn for logs 2016-10-26 04:06:29 -07:00
Carol Willing
4a622cb964 Merge pull request #831 from jupyterhub/willingc-patch-1
Remove duplicate word in docstring
2016-10-26 02:24:39 -07:00
Carol Willing
69e721de46 Remove duplicate word in docstring 2016-10-26 02:19:49 -07:00
Carol Willing
f3f130f452 Merge pull request #830 from minrk/services-todo
Flesh out custom services examples
2016-10-26 02:16:39 -07:00
Min RK
fd4a04e3f3 docs review 2016-10-26 10:22:54 +02:00
Min RK
85c040ab8e flesh out custom services doc 2016-10-25 13:28:13 +02:00
Min RK
2bb4cd4739 allow HubAuthenticated to check groups 2016-10-25 13:27:57 +02:00
Min RK
4c3b134f10 add flask whoami service
for a non-tornado example
2016-10-25 13:24:46 +02:00
Carol Willing
bb8536b553 Merge pull request #826 from Scrypy/issue-822
Updated spawner docs
2016-10-24 23:21:00 -07:00
Carol Willing
8998fd480c Merge pull request #829 from Todd-Z-Li/issue-823
Added funky ascii art to previous TODO messages.
2016-10-24 18:40:25 -07:00
Carol Willing
d948fed0b5 Merge pull request #828 from temogen/deldoc
Deleted IPython from howitworks doc.
2016-10-24 18:38:17 -07:00
Daniel Anthony Noventa
fcfe6314ac Delted IPython from howitworks docs. 2016-10-24 19:13:57 -05:00
Todd
dcfe2aa792 Added funky ascii art to previous TODO messages. 2016-10-24 19:03:21 -05:00
Danowsky
85790ab9d8 Updated spawner docs 2016-10-24 18:57:17 -05:00
Min RK
adda2fcd90 Don't assume empty state means not running
Some Spawners may not need state,
and they should be allowed to resume on Hub restart as well.

Adds some detail about when .poll may be called and how it should behave in less obvious circumstances
2016-10-21 16:28:40 +02:00
Min RK
5604e983db Merge pull request #818 from minrk/unmanaged-no-start
don’t try to start unmanaged services
2016-10-19 10:44:14 +02:00
Min RK
386563a10a don’t try to start unmanaged services 2016-10-18 16:18:03 +02:00
Min RK
0e3c5cf625 statsd typo 2016-10-18 16:17:49 +02:00
Min RK
a3eb2d2b9a Merge pull request #815 from kinuax/fix-setting-in-configuration-example
Fix setting in configuration example
2016-10-14 13:03:45 +02:00
Asier
b6a8860a44 Fix setting in configuration example 2016-10-13 13:45:23 -05:00
Carol Willing
b8a649ae86 Add error message when generate config path does not exist 2016-10-13 07:20:38 -07:00
Min RK
7774bfc612 Merge pull request #811 from willingc/quick-install
Sync quick install steps with PyData tutorial
2016-10-13 10:56:55 +02:00
Carol Willing
9f76613aed Sync quick install steps with PyData tutorial 2016-10-12 18:06:11 -07:00
Min RK
f1ccbe4bed Merge pull request #807 from willingc/normalize-whitelist
Add tests for username normalization
2016-10-12 16:21:19 +02:00
Carol Willing
668d78f729 Add tests for username normalization 2016-10-11 16:44:24 -07:00
Min RK
0009b9a3d6 Merge pull request #805 from danielballan/template-vars
MNT: Add hub host and prefix to template vars in prep for JLab extension
2016-10-11 18:18:21 +02:00
danielballan
b2be07ea6a MNT: Add hub host and prefix to template vars in prep for JLab extension. 2016-10-11 11:27:50 -04:00
Min RK
74649eaad0 Merge pull request #804 from willingc/ssl-termination
Clarify deprecation of --no-ssl
2016-10-11 12:08:55 +02:00
Carol Willing
f33086aa13 Clarify deprecation of --no-ssl 2016-10-10 12:05:39 -07:00
Min RK
9c1cd960fc Merge pull request #801 from minrk/warn-about-direct-connect
try to detect and warn about connecting directly to the Hub
2016-10-10 10:36:50 +02:00
Min RK
3a5226ffa0 Merge pull request #802 from minrk/spawn-pending-finish
add User.waiting_for_response
2016-10-07 11:53:04 +02:00
Min RK
96a53f9921 Merge pull request #797 from ianabc/redirection_loop
spawn_pending set too soon causing redirect loop
2016-10-07 11:13:09 +02:00
Min RK
ff92ac9dad more mocking in tests
avoids no_patience state leaking into other tests
2016-10-07 10:59:32 +02:00
Min RK
933478bfff add waiting_for_response indicator on User
.spawn_pending used for the *whole* window, from request to responsive (added to proxy)
.waiting_for_response is just used for the window between Spawner.start returning (process started, http endpoint known) and http endpoint becoming responsive

.waiting_for_response will never be True while .spawn_pending is False
2016-10-07 10:59:05 +02:00
Min RK
7d996f91b0 try to detect and warn about connecting directly to the Hub
This is guaranteed to result in a redirect loop.
2016-10-07 10:16:21 +02:00
Min RK
c818cbb644 Merge pull request #799 from willingc/doc-install
Move README installation instructions to docs
2016-10-06 19:46:51 +02:00
Carol Willing
e638e5b684 Move README installation instructions to docs 2016-10-06 04:37:57 -07:00
Ian Allison
625e76ea40 spawn_pending set too soon causing redirect loop
Signed-off-by: Ian Allison <iana@pims.math.ca>
2016-10-05 13:28:52 -07:00
Min RK
f8229c9fb6 Merge pull request #793 from willingc/slimconfpy
Slim conf.py comments and options cruft
2016-10-04 15:04:32 +02:00
Min RK
47da422a93 Merge pull request #758 from willingc/update-changes
Add changes for 0.7 release
2016-10-04 14:47:00 +02:00
Carol Willing
3dd98bc0fc Slim conf.py comments and options cruft 2016-10-04 05:28:03 -07:00
Carol Willing
fa6e4aa449 Add pr 789 deprecate --no-ssl 2016-09-30 09:02:58 -07:00
Carol Willing
182472f921 Changes per @minrk review 2016-09-30 08:57:35 -07:00
Carol Willing
d99afe531d Add changes for 0.7 release 2016-09-30 08:57:35 -07:00
Carol Willing
b6b238073f Merge pull request #789 from minrk/deprecate-no-ssl
Deprecate `--no-ssl`
2016-09-30 08:42:07 -07:00
Min RK
a4c696d3bd Merge pull request #788 from willingc/warehouse
Update link to docs
2016-09-30 17:03:34 +02:00
Min RK
bce767120c Merge pull request #785 from willingc/devclarity
Clarify docstring
2016-09-30 16:58:23 +02:00
Min RK
6a9f346b21 Deprecate --no-ssl
it's unnecessarily pedantic. Just warn instead.
2016-09-30 16:16:33 +02:00
Carol Willing
d4646e1caa Update link 2016-09-28 20:54:57 -07:00
Carol Willing
77f0e00695 Clarify docstring 2016-09-28 07:36:29 -07:00
Carol Willing
26a6c89b3a Merge pull request #778 from minrk/shutdown-services
cleanup managed services in shutdown
2016-09-27 09:53:50 -07:00
Carol Willing
34297b82b3 Merge pull request #777 from minrk/service-cookie
Work on service authentication
2016-09-27 09:53:12 -07:00
Carol Willing
70727c4940 Merge pull request #776 from minrk/cleanup-on-start
remove stopped users from proxy on startup
2016-09-27 09:51:01 -07:00
Min RK
56080e5436 Merge pull request #782 from spoorthyv/master
Updated Logos To Match New Brand Guidelines
2016-09-27 15:41:44 +02:00
spoorthyv
309b1bda75 Updated Logos 2016-09-26 15:56:11 -07:00
Min RK
f3ebb694b4 Merge pull request #780 from minrk/travis-no-verbose-pip
remove -v from pip install on travis
2016-09-26 17:06:44 +02:00
Min RK
f35c14318a Merge pull request #779 from minrk/docker-cdn
Dockerfile: set debian CDN
2016-09-26 17:06:01 +02:00
Min RK
b60f2e8233 remove -v from pip install on travis
it makes way too much noise
2016-09-26 17:03:51 +02:00
Min RK
f1a55e31ce Dockerfile: set debian CDN
because the default httpredir fails with some regularity

based on info from http://deb.debian.org
2016-09-26 16:58:31 +02:00
Min RK
2432611264 cleanup managed services in shutdown
don’t leave them running
2016-09-26 15:20:34 +02:00
Min RK
729b608eff Fix setting cookie for services
and exercise it in tests
2016-09-26 14:30:00 +02:00
Min RK
eb3252da28 simplify whoami service example
rely on defaults in HubAuthenticated to show how simple it can be
2016-09-26 14:18:54 +02:00
Min RK
a9e9338ee4 get HubAuth defaults from service env variables
allows use of HubAuthenticated without any arguments
2016-09-26 14:13:04 +02:00
Min RK
aad063e3cd remove stopped users from proxy on startup
We already added running users, but we didn't handle removing users from the proxy
if the user's server was stopped (e.g. while the Hub was restarting).
2016-09-26 13:20:42 +02:00
Min RK
be00265d1a Merge pull request #762 from willingc/swagger
Edit descriptions in API spec for user clarity
2016-09-25 14:39:42 +02:00
Min RK
335ba4f453 Merge pull request #771 from willingc/faq-adds
Added navigation links and workshop best practices
2016-09-25 14:38:45 +02:00
Carol Willing
5a4f3a4910 Added navigation links and workshop best practices 2016-09-22 10:02:29 -07:00
Carol Willing
7ee4be0f13 Remove api review notes doc 2016-09-22 09:13:39 -07:00
Carol Willing
10c3fbe5cf Add changes per @minrk 2016-09-22 09:12:26 -07:00
Carol Willing
13826a41a1 Merge pull request #769 from minrk/service-start-yield
service.start is not a coroutine
2016-09-22 03:21:47 -07:00
Min RK
cb35026637 service.start is not a coroutine
don’t yield it
2016-09-22 12:04:31 +02:00
Min RK
24c080cf4a Merge pull request #768 from minrk/service-url
only set service URL env if there's a URL to set
2016-09-22 11:57:44 +02:00
Min RK
e9fc629285 only set service URL env if there's a URL to set
These fields are only relevant for services with a web endpoint
2016-09-21 12:39:07 +02:00
Min RK
150b67c1c9 Merge pull request #761 from willingc/apidocs
Update API docs
2016-09-21 10:34:57 +02:00
Carol Willing
acdee0ac29 Change notes from txt to md 2016-09-19 12:05:26 -07:00
Carol Willing
193b236ef1 Add additional review questions re: API 2016-09-19 11:52:43 -07:00
Carol Willing
1851e6a29d Edit descriptions in API spec for user clarity 2016-09-19 10:49:56 -07:00
Carol Willing
74f086629c Update API docs 2016-09-19 08:42:28 -07:00
Min RK
33a59c8352 Merge pull request #757 from willingc/doc-contrib
Add contributor list to the docs and update the contents
2016-09-19 09:01:54 +02:00
Carol Willing
08644fea74 Add services to index/table of contents 2016-09-18 15:33:01 -07:00
Carol Willing
f878bf6ad3 Add contribution list to documentation 2016-09-18 15:29:54 -07:00
Carol Willing
651c457266 Add contributor list 2016-09-18 15:28:51 -07:00
Carol Willing
2dd3463ea8 Merge pull request #748 from minrk/string-formatting
Deprecate `%U` username substitution
2016-09-18 06:34:01 -04:00
Carol Willing
ad93af8cc8 Merge pull request #749 from minrk/single-user-help-all
exercise single-user help output
2016-09-18 06:33:38 -04:00
Min RK
080cf7a29b exercise single-user help output
and tweak some of its output
2016-09-15 13:04:09 +02:00
Min RK
b8f4803ef4 Deprecate %U username substitution
use Python format-strings instead.
2016-09-15 12:05:46 +02:00
Min RK
4a8f51ed6d Merge pull request #741 from willingc/add-lab
Add info on trying out JupyterLab
2016-09-13 10:31:49 +02:00
Carol Willing
7923074ed5 Add info on trying out JupyterLab 2016-09-12 22:22:22 -07:00
Min RK
834b2ba77d Merge pull request #739 from jupyterhub/fix-readme-1
Add --no-ssl to docker run command in README
2016-09-10 10:55:41 +02:00
Yuvi Panda
7897a13ca5 Add --no-ssl to docker run command
Otherwise this doesn't run by default, and someone in gitter ran into this earlier.
2016-09-09 10:57:19 -07:00
Min RK
7987011372 Merge pull request #738 from willingc/inspired-zulip
Add navigation to README
2016-09-09 13:38:22 +02:00
Min RK
d7a76077bd Merge pull request #734 from minrk/deprecated-local-spawner-subclasses
backward-combat for ip, port in LocalProcessSpawner subclasses
2016-09-09 13:37:58 +02:00
Min RK
62731cf489 Merge pull request #727 from willingc/servicespec
Edit Services document
2016-09-09 10:29:10 +02:00
Carol Willing
5d501bc465 Add navigation to README 2016-09-08 22:41:44 -07:00
Kyle Kelley
63a6841848 Merge pull request #737 from willingc/issue438
Add info on configuring pySpark executors on YARN
2016-09-08 17:59:24 -05:00
Carol Willing
403241bd98 Add reference to official pySpark docs 2016-09-08 15:28:54 -07:00
Carol Willing
de3fe88df6 Fix code indentation for markdown 2016-09-08 15:11:25 -07:00
Carol Willing
6a370286e1 Add info on setting pySpark executors on YARN 2016-09-08 15:09:20 -07:00
Carol Willing
491b7e7d11 Use Hub-Managed and Externally-Managed 2016-09-08 08:23:47 -07:00
Min RK
0b0db97117 Merge pull request #728 from willingc/cull-idle
Add readme to cull-idle example to demonstrate managed services
2016-09-08 16:57:16 +02:00
Min RK
42a993fd08 backward-combat for ip, port in LocalProcessSpawner subclasses
Subclasses prior to 0.6 may assume return value
of LocalProcessSpawner.start can be ignored
instead of passing it through.

For these cases, keep setting ip/port in the deprecated way
so that it still works with a warning,
rather than failing with the wrong port.
2016-09-08 16:54:52 +02:00
Carol Willing
fd1544bf41 Edits per @minrk's review 2016-09-08 07:16:25 -07:00
Carol Willing
ed36207328 Merge pull request #731 from willingc/issue654
Add config for default URL to FAQ
2016-09-08 07:05:56 -07:00
Carol Willing
a0b8ccf805 Add config for whole filesystem access and user home directory as default 2016-09-08 06:54:23 -07:00
Min RK
9d2278d29b Merge pull request #733 from willingc/issue594
Add troubleshooting info about sudospawner
2016-09-08 14:51:57 +02:00
Min RK
df42385d7e Merge pull request #732 from willingc/issue632
Add info on updates and Qualsys SSL analyzer to docs
2016-09-08 14:51:42 +02:00
Min RK
02796d4daa Merge pull request #730 from willingc/issue661
Add install instructions with no network to FAQ
2016-09-08 14:50:44 +02:00
Carol Willing
80c5f67335 Add troubleshooting info about sudospawner 2016-09-08 00:57:17 -07:00
Carol Willing
0b14e89404 Add info on updates and Qualsys SSL analyzer to docs 2016-09-07 22:00:33 -07:00
Carol Willing
f595b1ad59 Add clarification re: run on hub not each single user server 2016-09-07 21:21:10 -07:00
Carol Willing
80ca1eacc5 Add install instructions with no network to FAQ 2016-09-07 21:06:56 -07:00
Carol Willing
5b3ac6c840 Add readme to cull-idle example 2016-09-07 14:01:46 -07:00
Carol Willing
0000b7447a Make command consistent with examples/cull-idle 2016-09-07 13:52:33 -07:00
Carol Willing
a22060ca7f Edit Services document 2016-09-07 11:39:15 -07:00
Min RK
8ca321ecc3 Merge pull request #705 from minrk/actual-services
WIP: implement services API
2016-09-07 13:43:54 +02:00
Min RK
862cb3640b Merge pull request #722 from minrk/setuptools-no-egg
always install with setuptools
2016-09-07 13:38:06 +02:00
Min RK
51908c9673 clarifications from review 2016-09-07 13:19:09 +02:00
Min RK
9aa4046093 always install with setuptools
but not eggs (effectively require pip install .)
2016-09-05 15:46:20 +02:00
Min RK
acb49adfea Merge pull request #719 from Mistobaan/patch-1
fix docker repository
2016-09-05 10:38:12 +02:00
Fabrizio Milo
f345ad5422 fix docker repository 2016-09-02 14:45:16 -07:00
Min RK
5ad618bfc1 add API endpoint for services 2016-09-02 15:19:45 +02:00
Min RK
26b00578a1 remove redundant user_url utility
public_url works for users now
2016-09-02 13:22:49 +02:00
Min RK
c3111b04bb support services subdomain
- all services are on the 'services' domain, share the same cookie
2016-09-02 13:21:46 +02:00
Min RK
a61ba74360 Merge pull request #717 from minrk/hubauth-defaults
HubAuth login_url changes:
2016-09-02 12:05:17 +02:00
Min RK
4de93fd1d5 Merge pull request #718 from willingc/sdist-one
Remove zip from sdist build per PEP 527
2016-09-02 11:45:44 +02:00
Min RK
46bb7b05f4 strict host matching by including / 2016-09-02 11:44:51 +02:00
Carol Willing
1aa2cb1921 Remove zip from sdist build per PEP 527 2016-09-01 07:33:10 -07:00
Min RK
c4bfa63fd6 allow full URLs for login redirects iff they are for our host 2016-09-01 15:10:02 +02:00
Min RK
4c5d6167bd use just path for default hub auth login_url 2016-09-01 15:07:00 +02:00
Min RK
9a002c2445 update services doc with some feedback 2016-09-01 15:01:02 +02:00
Min RK
f97d32c5bd add services to the proxy
and start test coverage
2016-09-01 14:46:34 +02:00
Min RK
bac311677f Merge pull request #711 from willingc/update-change
Update changelog format
2016-08-29 12:01:08 +02:00
Carol Willing
94cb5b3a05 Update changelog format 2016-08-29 02:39:39 -07:00
Carol Willing
ed4f0ba014 Merge pull request #707 from willingc/mytheme
Update conda env and conf.py for clean build
2016-08-28 10:42:49 -07:00
Carol Willing
fd219b5fff Update conda env and conf.py for clean build 2016-08-28 10:08:00 -07:00
Min RK
140c4f2909 use services API in cull-idle example 2016-08-27 13:23:45 +02:00
Min RK
a1c787ba5f basic implementation of managed services
- managed services are automatically restarted
- proxied services not there yet
2016-08-27 12:59:26 +02:00
Min RK
54c808fe98 Service specification document 2016-08-26 17:25:53 +02:00
Min RK
eaeec9f19b Merge pull request #693 from willingc/doc-revise
Documentation refresh
2016-08-24 23:05:54 +02:00
Min RK
21d25ac130 Merge pull request #689 from minrk/log-add-user-error
log errors adding users already in db
2016-08-21 22:19:39 +02:00
Min RK
eda21642bd log errors adding users already in db
avoids removal of system users preventing Hub startup
2016-08-21 22:07:46 +02:00
Carol Willing
aace54d5b2 Merge pull request #699 from jhamrick/swarm-docs
Remove link to SwarmSpawner
2016-08-19 20:41:18 -07:00
Jessica B. Hamrick
e460c00759 Remove link to SwarmSpawner 2016-08-20 02:02:08 +01:00
Carol Willing
678fd1cd08 Shorten name 2016-08-18 10:36:40 -07:00
Carol Willing
42c78f3c43 Drop back to old environment 2016-08-18 10:20:57 -07:00
Carol Willing
548e0f6153 Edits to technical overview 2016-08-18 09:58:37 -07:00
Carol Willing
31f63c737f Add image of JupyterHub parts to index 2016-08-18 09:15:48 -07:00
Carol Willing
71b35602d7 Edit grammar in index 2016-08-18 08:36:46 -07:00
Carol Willing
7c41a024ba Fix typo 2016-08-18 05:05:46 -07:00
Carol Willing
51097de43d Update contents format 2016-08-18 04:52:51 -07:00
Carol Willing
44e16d538d Edit and corrections 2016-08-18 04:52:22 -07:00
Carol Willing
f6517d01db Move 'Using API' to user guide 2016-08-18 04:51:48 -07:00
Carol Willing
039b925cf6 Edit config-examples 2016-08-18 04:50:11 -07:00
Carol Willing
bba5460236 Simplify formating of troubleshooting doc 2016-08-18 04:49:30 -07:00
Carol Willing
e5d3705a1a Edit headings for authenticators and spawners docs 2016-08-18 04:48:43 -07:00
Carol Willing
7b80b95a49 Add checks for spelling 2016-08-18 04:47:21 -07:00
Carol Willing
75cb487ab3 Update conf 2016-08-17 15:11:57 -07:00
Carol Willing
eba4b3e8c7 More doc edits 2016-08-17 15:11:17 -07:00
Carol Willing
712b895d8e WIP refresh 2016-08-15 19:18:38 -07:00
Carol Willing
635fd9b2c3 Fix typo 2016-08-15 18:50:26 -07:00
Min RK
afcbdd9bc4 Merge pull request #678 from vilhelmen/swagger_fix
Swagger spec conformance
2016-08-04 13:06:00 +02:00
Will Starms
80fa5418b7 Fix missing description for responce 2016-08-03 16:59:14 -05:00
Will Starms
b0a09c027d Fix invalid type bool->boolean 2016-08-03 16:57:17 -05:00
Kyle Kelley
4edf59efeb Merge pull request #675 from minrk/api-info
Add /api/ and /api/info endpoints
2016-08-02 22:26:10 -05:00
Min RK
9f0dec1247 ignore generated rest-api html 2016-08-01 15:16:26 +02:00
Min RK
2c47fd4a02 Add /api/ and /api/info endpoints
/api/ is not authenticated, and just reports JupyterHub's version for now.
/api/info is admin-only, and reports more detailed info about Python, authenticators/spawners in use, etc.
2016-08-01 15:15:59 +02:00
Min RK
9878f1e32d Document parameters to shutdown API 2016-08-01 15:12:05 +02:00
Min RK
5c396668ff Merge pull request #671 from vilhelmen/swagger_fix
Fix timestamp type in API spec
2016-08-01 13:39:10 +02:00
Min RK
5f12f9f2c3 Merge pull request #667 from vilhelmen/master
Proxy will no longer recieve Hub's SIGINT
2016-08-01 11:04:39 +02:00
Will Starms
4974775cd9 Fix timestamp type 2016-07-31 19:23:59 -05:00
Will Starms
0cb777cd0f Switch to start_new_sesstion 2016-07-29 13:43:09 -05:00
Min RK
a4bb25a75f Merge pull request #604 from minrk/service-token
add Services to db
2016-07-29 10:32:15 +02:00
Min RK
b3f117bc59 Merge pull request #669 from vilhelmen/swagger_fix
Fix invalid license object and bad JSON pointers in API spec
2016-07-29 10:25:39 +02:00
Will Starms
499ba89f07 Correct invalid JSON pointers 2016-07-28 22:25:38 -05:00
Will Starms
05d743f725 Correct invalid license object in API spec 2016-07-28 22:19:05 -05:00
Carol Willing
a347d56623 Merge pull request #668 from willingc/toc-tweak
Minor additions to work done by @iamed18 in PR#602
2016-07-28 14:33:36 -07:00
Carol Willing
172976208e Minor additions to work done by @iamed18 in PR#602 2016-07-28 14:27:19 -07:00
Carol Willing
b6db3f59a2 Merge pull request #602 from iamed18/master
Added nginx reverse proxy example to GettingStarted.md
2016-07-28 14:09:31 -07:00
Carol Willing
4b31279fc8 Merge branch 'iamed18-master'
Closes #509
2016-07-28 14:01:29 -07:00
Edward Leonard
bfef83cefc separated configuration examples into their own document
Merge conflict resolved by @willingc
2016-07-28 13:58:20 -07:00
Edward Leonard
07d599fed2 added code-block ends
forgot them in last commit
2016-07-28 13:56:15 -07:00
Edward Leonard
0412407558 added example config with nginx reverse proxy 2016-07-28 13:56:15 -07:00
Edward Leonard
4c568b46d6 separated configuration examples into their own document 2016-07-28 14:17:51 -05:00
Michael Milligan
d92fcf5827 batchspawner URL change 2016-07-28 13:54:34 -05:00
Will Starms
36f3abbfc7 Proxy will no longer recieve Hub's SIGINT #665 2016-07-28 13:04:55 -05:00
Min RK
49a45b13e6 debug installation on travis 2016-07-28 17:23:44 +02:00
Min RK
dfa13cb2c5 avoid creating duplicate users in test_api
now that we check!
2016-07-28 17:23:44 +02:00
Min RK
fd3b959771 add api_tokens.service_id column with alembic 2016-07-28 17:23:44 +02:00
Min RK
39a80edb74 async fixes in test_init_tokens 2016-07-28 17:23:44 +02:00
Min RK
2a35d1c8a6 add service API tokens
service_tokens supersedes api_tokens,
since they now map to a new services collection,
rather than regular Hub usernames.

Services in the ORM have:

- API tokens
- servers (multiple, can be 0)
- pid (0 if not managed)
2016-07-28 17:23:44 +02:00
Min RK
81350322d7 Merge pull request #660 from willingc/remove-badge
Remove requires.io badge
2016-07-26 12:02:33 +02:00
Min RK
50c2528359 Merge pull request #659 from willingc/fix-restlink
Remove link and reflow text
2016-07-26 12:02:24 +02:00
Min RK
77bac30654 Merge pull request #650 from minrk/return-ip-port
return (ip, port) from Spawner.start
2016-07-26 12:02:13 +02:00
Carol Willing
41fafc74cf Merge pull request #662 from mwmarkland/master
Fix typo regarding user's interactions with PATH
2016-07-25 17:58:48 -07:00
Matthew Markland
c6281160fa Fix typo regarding user 2016-07-25 14:55:17 -05:00
Min RK
3159b61ae7 return (ip, port) from Spawner.start
removes the need for Spawners to set db state themselves in most cases

Should be backward-compatible with warnings.
2016-07-25 16:54:15 +02:00
Carol Willing
11278ddb26 Remove requires.io badge 2016-07-25 07:45:34 -07:00
Carol Willing
e299a6c279 Remove link and reflow text 2016-07-25 07:41:28 -07:00
Min RK
22ff5f3d91 Merge pull request #635 from minrk/traitlets-4.2-singleuser
use traitlets 4.2 API in singleuser script
2016-07-25 16:29:07 +02:00
Carol Willing
a3e8bd346f Merge pull request #656 from minrk/rest-api-docs
Add REST API to docs
2016-07-25 07:09:16 -07:00
Min RK
592a084a28 set API token in single-user-spawner test 2016-07-25 15:57:43 +02:00
Min RK
c27e59b0f9 better exit message if JPY_API_TOKEN is undefined. 2016-07-25 15:27:32 +02:00
Min RK
1c9bc1b133 traitlets 4.2 API in singleuser script 2016-07-25 15:27:32 +02:00
Min RK
be4f4853cf Merge pull request #655 from willingc/doc-rest
Add links to REST API docs
2016-07-25 10:51:08 +02:00
Carol Willing
7d8895c2fb Add links to swagger docs for REST API 2016-07-23 18:47:23 -07:00
Min RK
5b8913be5b install nodejs with conda on RTD 2016-07-23 12:23:30 +02:00
Min RK
d03a1ee490 build rest-api on RTD 2016-07-23 12:05:50 +02:00
Min RK
19ae38c108 add REST API to docs
include local build, even though it's not as nice as petstore.
Due the that, link to petstore as well.
2016-07-23 12:05:25 +02:00
Carol Willing
9b71f11213 Merge pull request #651 from minrk/check-hub-ip
more informative error if single-user server can't connect to Hub for auth
2016-07-22 07:30:27 -07:00
Min RK
8fbaedf4d7 more informative error if single-user server can't connect to Hub for auth
error message points to hub_ip setting if Hub doesn't appear to be accessible at 127.0.0.1
2016-07-22 15:35:24 +02:00
Min RK
87ab07b322 Merge pull request #646 from datapolitan/fix_juptyter
fixing start_proxy() that misspelled name of the project
2016-07-18 22:05:22 -07:00
Richard Dunks
f36a1e10e6 fixing start_proxy() that misspelled name of the project 2016-07-17 23:23:32 -04:00
Carol Willing
5944671663 Merge pull request #644 from JamiesHQ/doctypo
Fix link
2016-07-16 11:21:55 -05:00
Jamie W
27dfd0edca fix link 2016-07-16 11:18:14 -05:00
Min RK
9dfc043352 Merge pull request #639 from ryanlovett/patch-1
Correct Spawner.start typo
2016-07-13 17:10:17 -05:00
Min RK
e8bd1520b2 Merge pull request #640 from minrk/travis-pre-for-nathaniel
install dependencies with pre
2016-07-13 17:10:03 -05:00
Min RK
a30b9976f5 install dependencies with pre
to catch bugs introduced by dependencies during prerelease
2016-07-13 16:19:15 -05:00
Ryan Lovett
954e5b3d5e Correct Spawner.start typo
As documented at https://github.com/jupyterhub/jupyterhub/blob/master/jupyterhub/spawner.py#L103
2016-07-13 10:23:16 -07:00
Min RK
7cd8aa266b Merge pull request #634 from minrk/cleanup-after-yourself
cleanup servers, api tokens after spawner shutdown
2016-07-11 14:29:20 -05:00
Min RK
d0449d136c cascade on API token delete 2016-07-11 10:44:55 -05:00
Min RK
ff9aeb70b4 try ondelete=SET NULL in foreign keys 2016-07-09 12:13:04 +02:00
Min RK
2eaecd22ba cleanup servers, api tokens after spawner shutdown
prevents growing table of unused servers and tokens
2016-07-08 16:50:43 +02:00
Carol Willing
4801d647c1 Merge pull request #627 from minrk/alembic-util
allow running alembic with `python -m jupyterhub.dbutil`
2016-07-01 17:17:54 -07:00
Carol Willing
b7e6fa3abe Merge pull request #626 from minrk/check-permissions
Add a permissions-check hint when spawn fails with PermissionError
2016-07-01 17:02:37 -07:00
Min RK
d590024c47 allow running alembic with python -m jupyterhub.dbutil
since we only have generated alembic.ini, present a command that generates one and uses it.

enables generating new revisions with:

    python -m jupyterhub.dbutil revision -m msg
2016-07-01 14:38:31 +02:00
Min RK
f3f71c38c3 Merge pull request #620 from Fokko/fd-add-badge
Added requirements badge
2016-07-01 14:37:26 +02:00
Min RK
27125a169c Merge pull request #621 from minrk/user-redirect-handler
Add /user-redirect/ endpoint
2016-07-01 14:37:00 +02:00
Min RK
3f9205d405 Add a permissions-check hint when spawn fails with PermissionError 2016-07-01 14:36:34 +02:00
Carol Willing
96861dc2b0 Merge pull request #622 from minrk/getting-started-log
update log instructions in getting started
2016-06-24 08:52:31 -07:00
Min RK
cedaa184f1 update log instructions in getting started
use recommended output-piping instead of nonexistent log_file config
2016-06-24 17:15:50 +02:00
Fokko Driesprong
f491791081 Added requirements badge 2016-06-24 16:17:51 +02:00
Min RK
6bba1c474f Add /user-redirect/ endpoint
should avoid needing to cram user-detection / intent into other endpoints.
That functionality isn't removed,
but warnings are added indicating that /user-redirect/ should be used instead.
2016-06-24 16:08:30 +02:00
Carol Willing
357f6799b0 Merge pull request #613 from minrk/user-redirect-560
Finish up cross-user redirects
2016-06-16 08:32:03 -07:00
Carol Willing
ce3ea270f5 Merge pull request #612 from minrk/doc-links
fix links to authenticator/spawner pages from howitworks
2016-06-16 08:28:56 -07:00
Min RK
992717adc0 support cross-user redirects when JupyterHub is on a prefix 2016-06-16 15:42:00 +02:00
Min RK
993101710f fix links to authenticator/spawner pages from howitworks 2016-06-16 15:00:19 +02:00
Matthias Bussonnier
ac6fe61804 Merge pull request #609 from minrk/only-relevant-warning
hide http warning until it's relevant
2016-06-14 09:42:24 -07:00
Min RK
37aa1a291a Merge pull request #606 from minrk/rm-hub-prefix-option
disable hub_prefix config
2016-06-13 12:08:58 +02:00
Min RK
c6294f2763 Merge pull request #607 from Carreau/fix-bad-security-anchor-link
Fix bad anchor
2016-06-13 12:08:34 +02:00
Min RK
6e9a77f55f hide http warning until it's relevant
avoids flash of invalid warning when everything is correct
2016-06-13 12:07:52 +02:00
Min RK
799b407d89 Merge pull request #608 from Carreau/add-ssl-frontend-warning
Add a warning on login if page not over ssl.
2016-06-13 12:00:02 +02:00
Matthias Bussonnier
3ddfa5f939 Add a warning on login if page not over ssl.
The --no-ssl option in the backend make sens, but still too many
deployment are not over SSL because they underestimate / do not
understand the risks.
2016-06-12 13:24:46 -07:00
Matthias Bussonnier
5968661742 Fix bad anchor 2016-06-11 12:09:00 -07:00
Dara Adib
34592e3da5 Process single-user server redirects
Follow-up to #448.

If single-user notebook is running, it will redirect other
users to hub root with next argument, which was previously
ignored.
2016-06-10 17:15:48 +02:00
Min RK
5aea7eda96 disable hub_prefix config
it shouldn't be configurable
2016-06-10 17:14:47 +02:00
Edward Leonard
08024be1c0 added code-block ends
forgot them in last commit
2016-06-06 22:07:10 -05:00
Edward Leonard
39daff3099 added example config with nginx reverse proxy 2016-06-06 22:05:27 -05:00
Min RK
d4c0fe8679 Merge pull request #597 from minrk/single-user-service-auth
use HubAuth in single-user server
2016-06-06 13:31:40 +02:00
Min RK
c9ae45bef3 Merge pull request #599 from minrk/groups
Add groups
2016-06-04 21:22:29 +02:00
Min RK
503f21fd37 allow initializing groups from config
c.JupyterHub.load_groups creates groups and adds users to them.

It *does not* remove users from groups added previously.
2016-06-01 14:35:34 +02:00
Min RK
6d106b24f4 add groups API 2016-06-01 14:04:32 +02:00
Min RK
71f47b7a70 add user groups 2016-06-01 13:47:53 +02:00
Min RK
844381e7c9 use HubAuthenticated in jupyterhub-singleuser 2016-05-31 13:20:21 +02:00
Min RK
267994b191 move singleuser script into the package 2016-05-31 12:59:38 +02:00
Min RK
cc2202c188 Merge pull request #554 from minrk/service-auth
Add HubAuth for authenticating services with JupyterHub
2016-05-31 12:58:51 +02:00
Min RK
4996a84ca0 Merge pull request #596 from minrk/hub-prefix-traitlet
fix _hub_prefix_changed signature
2016-05-31 12:58:37 +02:00
Min RK
3cefc2951c fix _hub_prefix_changed signature
wasn't update for new traitlets API

c/o @Milly
2016-05-31 11:33:12 +02:00
Min RK
835b4afc06 Merge pull request #593 from minrk/redirect-typo
only strip base_url if it's actually there
2016-05-31 11:32:42 +02:00
Min RK
146bef1d88 test hub-authenticated tornado handler 2016-05-30 13:32:10 +02:00
Min RK
ef9656eb8b add example service 2016-05-30 13:32:10 +02:00
Min RK
84868a6475 add login_url to HubAuth
needed for tornado redirects. Still not sure the best way to pass it to tornado app settings.
2016-05-30 13:32:10 +02:00
Min RK
9e9c6f2761 document services.auth 2016-05-30 13:32:10 +02:00
Min RK
19e8bdacfe Add HubAuth for authenticating tornado-based services with JupyterHub
- HubAuth implements request to identify users with the Hub
- HubAuthenticated is a mixin for tornado handlers
2016-05-30 13:32:10 +02:00
Min RK
c6640aa51d only strip base_url if it's actually there 2016-05-30 10:34:33 +02:00
Min RK
1514a2f2e2 ignore .cache 2016-05-27 16:12:54 +02:00
Min RK
9edb282067 Merge pull request #591 from minrk/clean-css-fix
require clean-css 3.4.13
2016-05-27 13:12:09 +02:00
Min RK
9ffe5e6187 require clean-css 3.4.13
fixes node 6 compatibility
2016-05-26 18:31:10 +02:00
Min RK
14662111a8 Merge pull request #508 from minrk/alembic
Use alembic for database migrations
2016-05-26 15:40:44 +02:00
Min RK
a7ea5774d9 test database upgrades with alembic 2016-05-26 15:32:57 +02:00
Min RK
c998458362 include old-jupyterhub.sqlite generated by
I don't like including this, but I don't know a better way to get a starting db
other than doing a complete installation of old JupyterHub in an env.

At least it's small.
2016-05-26 15:32:50 +02:00
Min RK
07ddede40c typo: write db url in alembic 2016-05-26 15:31:49 +02:00
Min RK
b8a6ac62e8 include alembic in package_data 2016-05-26 14:23:10 +02:00
Min RK
86e9a3217c add jupyterhub upgrade-db entry point
don't do automatic upgrades (yet)

I'm not sure if auto upgrades are a good idea or not.
2016-05-26 14:17:41 +02:00
Min RK
f591e6e3fb require alembic 2016-05-26 14:17:41 +02:00
Min RK
64dd1db327 add User.auth_state column
a place for storing authenticator state,
and a simple test case for alembic.
2016-05-26 14:17:41 +02:00
Min RK
b68569f61c init alembic
prepare for database migration
2016-05-26 14:17:40 +02:00
Min RK
3a52e3f4df Merge pull request #589 from minrk/test-with-base-url
Run tests with an encoded base_url
2016-05-26 14:14:18 +02:00
Min RK
05c268e190 Run tests with an encoded base_url
to ensure we get our escaping right

Mostly revealed fixes needed in tests so far, not code,
but should catch regressions.
2016-05-26 13:56:20 +02:00
Carol Willing
98937de278 Merge pull request #586 from jupyterhub/willingc-patch-1
Fix typo in README link
2016-05-25 09:36:41 -07:00
Carol Willing
ff35e3b93e Fix typo in README link
Extra 's' on jupyter-notebook removed.
2016-05-25 09:12:10 -07:00
Carol Willing
4eebc95109 Merge pull request #585 from willingc/link-me
Fix RTD links to PDF
2016-05-25 09:02:39 -07:00
Carol Willing
c708c2a3a0 Fix RTD links to PDF back to org 2016-05-25 08:46:54 -07:00
Kyle Kelley
35f8190128 Merge pull request #584 from willingc/wtd-readme
Edit README based on Write The Docs tips
2016-05-24 13:31:46 -07:00
Carol Willing
78b268ddef Edit README based on Write The Docs tips 2016-05-24 12:40:52 -07:00
Min RK
eb99060a25 Merge pull request #578 from willingc/doc-570
Add docs on chain certificates and configuration re: 570
2016-05-19 08:24:54 +02:00
Carol Willing
8e99f659f5 Fix link 2016-05-18 10:59:04 -07:00
Carol Willing
5c9e9d65b5 Add links to SSL section in docs 2016-05-18 10:52:49 -07:00
Carol Willing
3e768b7297 Add chained cert doc info from @ryanlovett and @LMtx 2016-05-18 10:34:38 -07:00
Kyle Kelley
aa2999210d Merge pull request #572 from PeterDaveHelloKitchen/image-optimize
Losslessly optimize images using Google zopflipng
2016-05-16 09:33:59 -05:00
Peter Dave Hello
be95a27597 optimize images 2016-05-16 21:46:53 +08:00
Kyle Kelley
5edcdd4fb2 Merge pull request #567 from minrk/less-271
require less-2.7.1
2016-05-12 07:12:32 -05:00
Min RK
b81586de0a require less-2.7.1
2.7.0 has compatibility problems with source maps
2016-05-12 10:32:52 +02:00
Carol Willing
e0f3e3b954 Merge pull request #559 from ozancaglayan/doc-fix-apitoken
doc: Add section about API tokens
2016-05-09 05:57:56 -07:00
Ozan Çağlayan
3037d264c3 docs: Fix last two typos 2016-05-05 15:41:38 +03:00
Ozan Çağlayan
17f1346c08 doc: address reviewers comments 2016-05-04 18:15:15 +03:00
Ozan Çağlayan
276aba9f85 doc: Add section about API tokens 2016-05-04 17:35:54 +03:00
Min RK
0ba63c42fd back to dev 2016-05-04 14:09:47 +02:00
Min RK
2985562c2f release 0.6.1 2016-05-04 14:08:39 +02:00
Min RK
754f850e95 changelog for 0.6.1 2016-05-04 14:08:39 +02:00
Min RK
dccb85d225 plural add-users ids 2016-05-04 13:57:16 +02:00
Min RK
a0e401bc87 Merge pull request #551 from minrk/proxy-error
Serve proxy error pages from the Hub
2016-05-04 12:34:10 +02:00
Min RK
c6885a2124 Merge pull request #552 from minrk/poll-and-notify
notice dead servers more often
2016-05-04 12:33:09 +02:00
Min RK
7528fb7d9b notice dead servers more often
call poll_and_notify to ensure triggering of dead-server events in a few places:

- `/hub/home` page view
- user start and stop API endpoints

This should avoid the failure to stop a server that's died uncleanly because the server hasn't noticed yet
2016-05-04 11:07:28 +02:00
Carol Willing
e7df5a299c Merge pull request #556 from minrk/shutdown-all
Add Stop All button to admin page
2016-05-03 05:58:41 -07:00
Min RK
ff997bbce5 Add Stop All button to admin page
for stopping all single-user servers at once
2016-05-03 13:25:12 +02:00
Min RK
1e21e00e1a return status from poll_and_notify
allows calling it directly
2016-04-27 14:28:23 +02:00
Min RK
77d3ee98f9 allow logo_url in template namespace to set the logo link 2016-04-27 14:06:51 +02:00
Min RK
1f861b2c90 server proxy error pages from the Hub 2016-04-27 14:06:29 +02:00
Carol Willing
14a00e67b4 Merge pull request #550 from daradib/typo
Fix docs typo for Spawner.disable_user_config
2016-04-26 15:28:02 -07:00
Dara Adib
14f63c168d Fix docs typo for Spawner.disable_user_config 2016-04-26 11:36:48 -07:00
Kyle Kelley
e70dbb3d32 Merge pull request #549 from minrk/optional-statsd
Make statsd an optional dependency
2016-04-26 07:46:28 -05:00
Min RK
b679275a68 remove unneeded codecov.yml
codecov team config suffices
2016-04-26 13:44:29 +02:00
Min RK
0c1478a67e Make statsd an optional dependency
only import it if it's used
2016-04-26 13:37:39 +02:00
Min RK
d26e2346a2 Merge pull request #548 from minrk/jupyterhub-urls
fix a few more jupyter->jupyterhub URLs
2016-04-26 12:41:19 +02:00
Min RK
9a09c841b9 Merge pull request #547 from minrk/disable-codecov-comments
disable codecov PR comments
2016-04-26 12:41:02 +02:00
Min RK
f1d4f5a733 fix a few more jupyter->jupyterhub URLs
in README
2016-04-26 11:58:27 +02:00
Min RK
d970dd4c89 disable CodeCov PR comments
The've removed web app config, in favor of codecov.yml,
discarding our existing config,
which means coverage reports are showing up in most Jupyter PRs now.
2016-04-26 11:55:52 +02:00
Min RK
f3279bf849 Merge pull request #544 from rafael-ladislau/master
Fix multiple windows logout error
2016-04-26 11:41:53 +02:00
Rafael Ladislau
db0878a495 Fix multiple windows logout error
When you have two JupyterHub windows and log out successfully in one of them. If you try to click the logout button in the other window, you will receive a 500 error.

It happened because there were operations being done in a None user object.
2016-04-25 13:31:39 -04:00
Min RK
c9b1042791 back to dev 2016-04-25 14:34:15 +02:00
Min RK
cd81320d8f push tags on circleci 2016-04-25 14:25:34 +02:00
Min RK
3046971064 release 0.6 2016-04-25 14:10:29 +02:00
Min RK
30498f97c4 Merge pull request #543 from robnagler:master
Allow jupyterhub-singleuser to run on python 2 install

closes #543
2016-04-25 11:35:40 +02:00
robnagler
d9d68efa55 run with default python, which might be python 2 2016-04-25 11:31:17 +02:00
Min RK
4125dc7ad0 Merge pull request #542 from willingc/doc-addition
Add troubleshooting documentation for 500 issue
2016-04-22 15:23:28 +02:00
Carol Willing
13600894fb Changed link re: Min's tip 2016-04-22 06:11:53 -07:00
Carol Willing
1b796cd871 Add links 2016-04-22 05:37:30 -07:00
Carol Willing
e7889dc12e Add 500 error to troubleshooting docs 2016-04-22 05:36:15 -07:00
Carol Willing
244a3b1000 Merge pull request #541 from minrk/cookie-referer
check referer only if there is a valid user cookie
2016-04-22 05:03:05 -07:00
Carol Willing
05dfda469f Merge pull request #540 from minrk/0.6
Changelog for 0.6
2016-04-22 04:21:44 -07:00
Min RK
6b19ee792d check referer only if there is a valid user cookie
avoids misleading "Blocking Cross Origin..." message
when there's no logged-in user for API requests.
2016-04-22 13:16:13 +02:00
Min RK
ace38d744a Changelog for 0.6 2016-04-22 12:50:49 +02:00
Min RK
56a5ed8c87 Merge pull request #539 from minrk/unused-email
add ignored -e arg to docker login
2016-04-22 10:50:15 +02:00
Min RK
60e8a76476 add ignored -e arg to docker login
doesn't appear to be needed on more recent docker
2016-04-22 10:24:40 +02:00
Min RK
552800ceb7 add sec doc
reviewed on security list
2016-04-22 10:20:18 +02:00
Carol Willing
7dd1900f5f Merge pull request #521 from minrk/docker-onbuild
Move docker onbuild step to jupyterhub-onbuild
2016-04-21 18:26:43 -07:00
Min RK
35c261d0ed better Dockerfile comments from Carol 2016-04-21 21:32:36 +02:00
Min RK
fa34ce64b7 include dockerfiles in manifest 2016-04-21 13:50:35 +02:00
Min RK
f0504420a9 move docker onbuild to directory 2016-04-21 13:50:27 +02:00
Min RK
8666f3a46c push onbuild image to docker hub with circle-ci 2016-04-21 13:38:15 +02:00
Carol Willing
60d6019cf7 Merge pull request #534 from jupyterhub/willingc-patch-1
Fix post move links to jupyterhub org in README
2016-04-20 20:05:39 -07:00
Carol Willing
173daeeb09 Fix post move links to jupyterhub org in README 2016-04-20 20:00:18 -07:00
Carol Willing
cf988dca4d Merge pull request #531 from minrk/extra-log-file-doc
[DOC] Note that extra_log_file only affects Hub's logs
2016-04-20 06:00:01 -07:00
Min RK
ffc2faabf7 [DOC] Note that extra_log_file only affects Hub's logs
not single-user server logs, or anything else.
2016-04-20 14:45:22 +02:00
Min RK
9fed0334c8 jupyterhub path in dockerfiles 2016-04-20 14:43:25 +02:00
Min RK
8b61eb7347 install from miniconda 4.0.5
- checksum miniconda installer
- move jupyterhub src to /src/jupyterhub
2016-04-19 13:21:25 +02:00
Min RK
9cdda101c7 Move onbuild step to jupyterhub-onbuild
Removes onbuild from from jupyter/jupyterhub image,
though it remains incomplete and will not run without a config file.
2016-04-19 13:21:24 +02:00
Carol Willing
f3bbca80ea Merge pull request #528 from minrk/test-cookie-secret
exercise cookie secret loading in tests
2016-04-19 04:01:36 -07:00
Carol Willing
ce30f28449 Merge pull request #527 from minrk/polish-520
polish cookie-secret PR
2016-04-19 03:56:41 -07:00
Min RK
6cb58c17e7 exercise cookie secret loading in tests 2016-04-19 11:15:48 +02:00
Min RK
183e244490 polish cookie-secret PR
- fix a couple of typos
- use ValueError instead of assert to ensure error is raised even when Python optimizes-out asserts
2016-04-19 10:15:10 +02:00
Min RK
d5cd5115a5 Merge pull request #520 from robnagler/master
cookie_secret file must be base64
2016-04-19 10:10:58 +02:00
robnagler
bbd3b22490 incorrect log call in previous checkin 2016-04-18 16:25:03 +00:00
robnagler
e02daf01ad Fix jupyter/jupyterhub#520: exit if any errors parsing file; Also, fix abstraction use of getenv/os.environ (use one or the other, not both) 2016-04-18 15:35:31 +00:00
robnagler
af1e253f8a Fix jupyter/jupyterhub#522 2016-04-18 15:16:01 +00:00
Min RK
491da69994 typo 2016-04-18 12:51:35 +02:00
Min RK
0737600d3c Merge pull request #515 from proversity-org/master
Post handler for  requesting authorization tokens; authenticated via form.
2016-04-18 11:23:24 +02:00
dominic
c7f542e79e Add tests for form based token generation 2016-04-18 10:27:38 +02:00
robnagler
21213c97c6 cookie_secret file is decoded by binascii.a2b_base64 so need to document it must be Base64. Added better doc for other values, and included description of "cookie_secret" parameter as well 2016-04-17 23:35:06 +00:00
Carol Willing
b36cd92ae6 Merge pull request #517 from minrk/load-tokens
allow pre-loading API tokens from config
2016-04-15 06:49:40 -07:00
Min RK
094ac451c7 Don't allow bad tokens to create tokens in the db 2016-04-15 12:42:52 +02:00
Min RK
fa4b666693 allow pre-loading API tokens from config
This is the first small part of easing the pain of services,
which is generating the API tokens,
and used to require initializing the JupyterHub database.
2016-04-14 16:45:40 +02:00
Carol Willing
ce9dc2093c Merge pull request #514 from minrk/docker-readme
revisions to docker notes
2016-04-14 07:05:02 -07:00
dominic
9fd97a8d63 Keep line spacing consistent. Don't do anything if authenticator not defined. 2016-04-14 15:39:26 +02:00
Min RK
2261a0e21d revisions to docker notes
- link to Docker docs on volumes
- name container `jupyterhub`
- wording
2016-04-14 15:35:58 +02:00
dominic
a7a1c32a03 Add post handler for form based auth 2016-04-14 09:32:42 +02:00
Matthias Bussonnier
dfd01bbf5f Merge pull request #503 from minrk/disable-npm-progress
disable npm progress when installing
2016-04-08 17:36:02 -07:00
Min RK
b11a5be781 disable npm progress when installing
apparently faster, but should also fix unicode errors
2016-04-08 16:35:23 -07:00
Kyle Kelley
8b6950055b Merge pull request #501 from minrk/set-login-at-root-redirect
set login cookie when redirecting
2016-04-06 12:35:50 -05:00
Min RK
e8a298be00 set login cookie when redirecting
should avoid one possible redirect-loop case when the single-user cookie is invalid, but the Hub cookie is valid.
2016-04-06 10:18:23 -07:00
Min RK
69f24acac2 Merge pull request #499 from yuvipanda/statsd
Emit metrics via statsd
2016-04-05 09:23:20 -07:00
YuviPanda
9ffebd0c5e Send metrics about various redirects from User spawning 2016-04-01 14:05:02 -07:00
YuviPanda
2dd3d3c448 Send timing info about spawner success / failure 2016-04-01 10:20:37 -07:00
YuviPanda
4644e7019e Send metrics about running and active users
Uses the standard user last-updated activity callback
2016-04-01 10:20:37 -07:00
YuviPanda
5a15d7a219 Actually start the timer 2016-04-01 10:20:37 -07:00
YuviPanda
788129da12 Send metrics for login and logout actions 2016-04-01 10:20:37 -07:00
YuviPanda
cac5175c9b Send CSP metrics to statsd 2016-04-01 10:20:37 -07:00
YuviPanda
80556360ac Add statsd to the base request handler 2016-04-01 10:20:37 -07:00
YuviPanda
3dca0df55f Add statsd to the base JupyterHub app
Not actually emitting any metrics yet
2016-04-01 10:20:37 -07:00
Min RK
62a5e9dbce Merge pull request #497 from yuvipanda/env-callable
Allow environment config values to be callable
2016-04-01 09:57:52 -07:00
YuviPanda
45fcdc75c0 Add docs about callables in environment configurable 2016-03-31 23:44:08 -07:00
Min RK
f1bdf6247a Merge pull request #500 from yuvipanda/fix-url-encoding-4
Use User.url instead of constructing it manually
2016-03-31 22:15:58 -07:00
YuviPanda
80932a51f4 Use User.url instead of constructing it manually
This fixes issues with URL encoding when redirecting users to
their own notebook instances
2016-03-31 17:28:33 -07:00
Min RK
c8774c44d4 Merge pull request #498 from yuvipanda/statsd-configurable
Mark statsd_prefix as configurable as well
2016-03-31 15:08:10 -07:00
YuviPanda
bf2629450c Mark statsd_prefix as configurable as well 2016-03-31 13:46:37 -07:00
YuviPanda
705ff78715 Allow environment config values to be callable
This allows deployments to configure environment variables
that need to be different for each user / container (such as
credentials for various services, etc).
2016-03-31 11:52:53 -07:00
Min RK
a13119a79f Merge pull request #496 from yuvipanda/statsd
Allow specifying statsd host/port/prefix info
2016-03-31 11:18:09 -07:00
YuviPanda
6932719e4e Convert port into string (so that .join works) 2016-03-31 10:32:49 -07:00
YuviPanda
68a750fc7a Use 'Integer' rather than 'Int' for config traitlet 2016-03-30 19:04:57 -07:00
YuviPanda
c6d05d0840 Allow specifying statsd host/port/prefix info
Currently only passes it through to CHP. This is needed
for the cases when JupyterHub spawns and maintains CHP.
2016-03-30 18:59:32 -07:00
Carol Willing
2bbfd75f4d Merge pull request #495 from Carreau/add-import
Import warnings, used on line 215, not imported.
2016-03-29 15:52:39 -07:00
Matthias Bussonnier
26f0e8ea5c Import warnings, used on line 215, not imported. 2016-03-29 15:36:22 -07:00
Carol Willing
552e5caa11 Merge pull request #494 from jupyter/Codecov-badge
Add codecov Badge.
2016-03-29 15:23:54 -07:00
Matthias Bussonnier
7753187e51 Add codecov Badge. 2016-03-29 15:04:17 -07:00
Carol Willing
bddadc7522 Merge pull request #493 from minrk/traitlets-4-1-again
use traitlets 4.1 APIs
2016-03-29 14:51:51 -07:00
Min RK
195eea55f3 log.warning 2016-03-29 09:22:32 -07:00
Min RK
7a2794af7c use traitlets-4.1 observe/default decorators 2016-03-27 10:41:36 -07:00
Min RK
fa48620076 use traitlets-4.1 .tag(config=True) API 2016-03-27 10:29:36 -07:00
Min RK
e4cfe01c4a require traitlets 4.1 2016-03-27 10:21:41 -07:00
Carol Willing
b35e506220 Merge pull request #479 from minrk/config-env
Make Spawner.env configurable
2016-03-24 07:59:44 -07:00
Carol Willing
dd3ed1bf75 Merge pull request #490 from minrk/disable-pam-session
Allow disabling PAM sessions
2016-03-24 07:57:00 -07:00
Min RK
40368b8f55 Allow disabling PAM sessions
it's often buggy and rarely necessary,
so allow it to be disabled when it's causing problems.

It's still on by default for backward-compatibility,
though maybe it shouldn't be.
2016-03-23 23:24:54 +01:00
Min RK
d0f1520642 Add Spawner.environment configurable
instead of making existing Spawner.env configurable

Spawner.env is deprecated
2016-03-22 13:48:26 +01:00
Carol Willing
28c8265c3d Merge pull request #487 from minrk/fix-failed-login-for-none
Fix 'failed login for None' message
2016-03-21 04:51:20 -07:00
Min RK
1d1a8ba78b Fix 'failed login for None' message
on failed login, get username from form data, not the guaranteed-None return value of authenticate
2016-03-21 12:01:31 +01:00
Min RK
a1c764593c travis_retry tests
to hide intermittent failures and enable laziness
2016-03-15 10:37:03 +01:00
Min RK
06902afa2d Merge pull request #481 from willingc/issue-417
Add additional documentation on --no-SSL option
2016-03-15 10:12:18 +01:00
Min RK
6d46f10cfa Merge pull request #480 from willingc/issue-458
Update the configuration section of docs
2016-03-15 10:11:54 +01:00
Carol Willing
b71f34eb3c Fix transposed version number 2016-03-14 16:57:12 -07:00
Carol Willing
11df935f34 Fix awkward wording 2016-03-14 16:54:04 -07:00
Carol Willing
19b6468889 Add no-SSL option to docs 2016-03-14 16:48:49 -07:00
Carol Willing
d2dddd6c82 Update the configuration section of docs, add example 2016-03-14 16:21:24 -07:00
Min RK
5d140fb889 Merge pull request #478 from willingc/readme-docker
Update README re: docker image contents
2016-03-11 22:24:27 +01:00
Matthias Bussonnier
2bf8683905 Merge pull request #477 from willingc/doc-sphinx
Use latest version of Sphinx to fix RTD "Edit on GitHub"
2016-03-11 10:46:52 -08:00
Carol Willing
2dba7f4f61 Update README re: docker image contents 2016-03-11 10:05:13 -08:00
Carol Willing
2820ba319f Update sphinx version for md on rtd 2016-03-11 07:55:49 -08:00
Min RK
be7a627c11 Make Spawner.env configurable
moves `_env_default` logic to `get_env`,
so that `Spawner.env` can be safely configurable
2016-03-11 12:34:49 +01:00
Matthias Bussonnier
2cb1618937 Merge pull request #467 from minrk/add-user-more-often
Call `add_user` more often
2016-03-10 14:45:56 -08:00
Min RK
c9e0c5fe04 Merge pull request #474 from minrk/user.url
allow user.url to be accessed without the server running
2016-03-10 10:28:11 +01:00
Min RK
922956def2 allow user.url to be accessed without the server running
Reduces the number of different ways we need to build the same URLs.
2016-03-09 09:30:50 +01:00
Min RK
c6c699ea89 Merge pull request #472 from yuvipanda/fix-user-encoding
Use encoded URL when redirecting user notebooks
2016-03-09 09:20:43 +01:00
YuviPanda
e0219d0363 Use encoded URL when redirecting user notebooks
Otherwise it breaks for usernames that have url unsafe
characters.
2016-03-08 18:41:35 -08:00
Matthias Bussonnier
f7dab558e4 Merge pull request #468 from minrk/clean-the-pool
set default pool_recycle if using mysql
2016-03-08 11:28:59 -08:00
Min RK
74e558dad2 set default pool_recycle if using mysql 2016-03-08 10:58:18 +01:00
Min RK
96269fac0f Call add_user more often
- Ensures add_user is called as part of startup *for all users*.
  This was previously only true for users not already in the db.
- Normalize usernames in whitelist and admin sets
- Call add_user on new users logged in when there is no whitelist.
2016-03-08 10:49:02 +01:00
Min RK
a0501c6ee4 set patch version to 0 on release 2016-03-08 09:55:44 +01:00
Min RK
ea2ed75ab2 back to dev 2016-03-08 09:00:41 +01:00
Min RK
fc6435825c release 0.5.0 2016-03-08 08:57:33 +01:00
Min RK
b3ab48eb68 Merge pull request #463 from minrk/moar-coverage
Increase some test coverage
2016-03-07 17:13:20 +01:00
Carol Willing
a212151c09 Merge pull request #461 from minrk/0.5
0.5 changelog
2016-03-07 08:07:19 -08:00
Min RK
67ccfc7eb7 increase some test coverage 2016-03-07 16:13:57 +01:00
Min RK
9af103c673 fixes for handling failed chdir in spawners 2016-03-07 15:12:30 +01:00
Min RK
82643adfb6 stop_pending also counts as not running 2016-03-07 14:27:40 +01:00
Min RK
74df94d15a 0.5 changelog 2016-03-07 13:54:40 +01:00
Min RK
da1b9bdd80 Merge pull request #460 from yuvipanda/mysql-fix
Add lengths to all Unicode() columns
2016-03-07 10:36:17 +01:00
Min RK
18675ef6df Merge pull request #453 from minrk/timeout-in-is-up
use the same connection check everywhere
2016-03-07 10:35:12 +01:00
YuviPanda
bf9dea5522 Add lengths to all Unicode() ones
- Otherwise does not work with MySQL
- Change JSONDict to be TEXT (Unbounded) rather than VARCHAR.
  This makes most sense, since you can't index these anyway.
- The 'ip' field in Server is set to 255, since that is the
  max allowed length of DNS entries.
- Most of the rest of the Unicodes have approximately high
  values that most people should not mostly run into
  (famous last words).
2016-03-06 18:26:25 -08:00
Min RK
62e30c1d79 Merge pull request #457 from shreddd/default_url
Enable default_url to pass in to notebook server
2016-03-06 10:33:52 +01:00
shreddd
1316196542 Update spawner.py
type
2016-03-05 12:24:39 -08:00
Shreyas Cholia
1a377bd03a comment on default_url being used with notebook_dir 2016-03-05 12:16:10 -08:00
Shreyas Cholia
66a99ce881 Add support for default_url 2016-03-05 12:05:58 -08:00
shreddd
481debcb80 Merge pull request #1 from jupyter/master
sync master
2016-03-05 12:04:09 -08:00
Carol Willing
03c25b5cac Merge pull request #452 from minrk/redundant-use-subdomain
remove redundant use_subdomains
2016-03-05 11:52:43 -08:00
Carol Willing
26c060d2c5 Merge pull request #456 from willingc/readme-clarify
Add minor clarification to README
2016-03-05 10:57:13 -08:00
Carol Willing
7ff42f9b55 Add @betatim's suggested wording 2016-03-05 10:43:45 -08:00
Carol Willing
a35d8a6262 Add minor clarification 2016-03-05 10:14:44 -08:00
Carol Willing
8f39e1f8f9 Merge pull request #455 from betatim/readme-fix
README uses two different names for docker container
2016-03-05 10:08:34 -08:00
Tim Head
ff19b799c4 container -> cont for consistency 2016-03-05 09:19:15 +01:00
Kyle Kelley
e547949aee Merge pull request #433 from minrk/disable-user-config
allow disabling user configuration of single-user servers
2016-03-04 09:57:45 -06:00
Min RK
31be00b49f failure to connect may be a timeout 2016-03-04 16:28:57 +01:00
Min RK
4533d96002 use the same connection check everywhere
avoids inconsistencies in error handling
2016-03-04 16:28:57 +01:00
Min RK
7f89f1a2a0 expose disable_user_config as Spawner.disable_user_config 2016-03-04 14:41:40 +01:00
Min RK
aed29e1db8 Simplify filter to exclude config in the home directory 2016-03-04 11:43:45 +01:00
Min RK
49bee25820 allow disabling user configuration of single-user servers 2016-03-04 11:43:45 +01:00
Min RK
838c8eb057 Merge pull request #448 from daradib/redirect
Redirect requests to logged in user
2016-03-04 11:15:56 +01:00
Min RK
be5860822d remove redundant use_subdomains
non-empty subdomain_host is enough
2016-03-04 11:11:41 +01:00
Dara Adib
5a10d304c9 Redirect user to login page when not logged in 2016-03-02 16:55:33 -08:00
Dara Adib
fdd3746f54 Add test for user redirect 2016-03-02 16:18:02 -08:00
Dara Adib
4d55a48a79 Redirect requests to logged in user
If a user, alice, requests /user/bob/notebooks/mynotebook.ipynb,
redirect her to /user/alice/notebooks/mynotebook.ipynb.
Currently, such requests get stuck in a redirect loop because
the request will be redirected to login page with a next parameter
that when followed is again redirected.

When notebook_dir is consistent across users, this will allow
users to share notebook URLs. Fixes #424.
2016-03-02 16:15:50 -08:00
Min RK
b2ece48239 reverse arguments in check_routes 2016-03-01 19:42:55 +01:00
Kyle Kelley
6375ba30b7 Merge pull request #445 from minrk/check-routes-pending
Don't add users with spawn_pending to the proxy
2016-03-01 09:19:42 -06:00
Min RK
f565f8ac53 Don't add users with spawn_pending to the proxy
check_routes checks for missing routes for running users.
This is meant for when the proxy has been relaunched outside the Hub.

If spawners are slow to start, it's possible for check_routes to fire in the middle of spawning,
triggering addition of the user's server (which has no defined location yet) to the proxy before it's up.
If the spawning fails, the route will remain indefinitely (because it never should have been added in the first place), and the user will see 503 until their server is launched manually again.

Checking `spawn_pending` in user.running prevents this.
2016-03-01 15:18:51 +01:00
Kyle Kelley
5ec05822f1 Merge pull request #436 from minrk/subdomains
allow running single-user servers on subdomains
2016-02-28 09:49:45 -06:00
Min RK
335b47d7c1 include protocol in subdomain_host
makes everything easier, and tests are passing with and without subdomains (yay!)
2016-02-28 11:12:41 +01:00
Min RK
f922561003 Tests are passing with subdomains 2016-02-26 17:32:55 +01:00
Min RK
79df83f0d3 Allow getting users by name 2016-02-26 17:32:55 +01:00
Min RK
29416463ff proxy needs user dict, which has proxy path
this won't be needed if/when I make a schema change, where domain is included in the Server table.
2016-02-26 17:32:55 +01:00
Min RK
dd2e1ef758 turn off subdomains by default 2016-02-26 17:32:55 +01:00
Min RK
a9b8542ec7 pass hub's host to single-user servers via hub_host 2016-02-26 17:32:54 +01:00
Min RK
a4ae2ec2d8 consolidate cookie setting in _set_user_cookie 2016-02-26 17:32:54 +01:00
Min RK
b54bfad8c2 [WIP]: allow running single-user servers on subdomains
relies on CHP's host-based routing (a feature I didn't add!)

requires wildcard DNS and wildcard SSL for a proper setup

still lots to workout and cleanup in terms of cookies and where to use host, domain, path, but it works locally.
2016-02-26 17:32:54 +01:00
Min RK
724bf7c4ce Merge pull request #441 from jupyter/revert-440-master
Revert "Do not consider `@` character url-safe"
2016-02-26 09:06:46 +01:00
Kyle Kelley
fccc954fb4 Merge pull request #442 from minrk/never-poll-before-start-is-done
avoid calling Spawner.poll during Spawner.start
2016-02-25 08:20:35 -06:00
Kyle Kelley
74385a6906 Merge pull request #443 from minrk/catch-options-from-form
catch exceptions in options_from_form
2016-02-25 08:19:16 -06:00
Min RK
dd66fe63c0 catch exceptions in options_from_form
Allows form validation to be implemented in options_from_form, as well as start.
2016-02-25 12:02:23 +01:00
Min RK
e74934cb17 avoid calling Spawner.poll during Spawner.start
moves `spawn_pending` flag to only around start, not the HTTP wait.

Some Spawners may not know how to poll until start has finished (DockerSpawner).
Let's not require that they do.
2016-02-25 10:13:51 +01:00
Min RK
450281a90a Revert "Do not consider @ character url-safe" 2016-02-25 09:04:25 +01:00
Kyle Kelley
6e7fc0574e Merge pull request #440 from ResearchComputing/master
Do not consider `@` character url-safe
2016-02-24 23:58:45 -06:00
Jonathon Anderson
fc49aac02b Do not consider `@' character url-safe
Usernames that have an `@'-separated domain component
break JupyterHub when the server expects to see query
strings that contain an `@', when browsers and other
clients send `%40'.
2016-02-24 16:48:23 -07:00
Kyle Kelley
097d883905 Merge pull request #435 from minrk/debug-no-server
add debug logging for adding users with no running server
2016-02-20 06:04:12 -08:00
Min RK
cb55118f70 add debug logging for adding users with no running server
in check_routes, it has been reported that users without a running server are attempted to be added.

So something is wrong, either in sqlalchemy or my understanding of what it does (likely the latter),
because a filter for users with a non-None server is returning at least one result whose server is None.
2016-02-20 14:22:50 +01:00
Carol Willing
2a3c87945e Merge pull request #434 from rgbkrk/ssl
Don't let the default include `--no-ssl`.
2016-02-18 16:48:06 -08:00
Kyle Kelley
2b2aacedc6 Don't let the default include --no-ssl. 2016-02-18 16:27:53 -08:00
Kyle Kelley
8ebec52827 Merge pull request #431 from ObiWahn/master
Update README.md
2016-02-18 16:25:56 -08:00
Jan Christoph Uhde
1642cc30c8 fix: run vs exec and split sentence 2016-02-19 00:13:02 +01:00
Kyle Kelley
1645d8f0c0 Merge pull request #432 from minrk/no-port-retries
disable port_retries in single-user server
2016-02-18 06:40:51 -08:00
Min RK
8d390819a1 disable port_retries in single-user server
since Spawners won't notice that the server has started somewhere other than where it was asked to
2016-02-18 09:03:45 +01:00
Jan Christoph Uhde
c7dd18bb03 Update README.md 2016-02-16 22:58:27 +01:00
Min RK
84b7de4d21 set x bit on jupyterhub-singleuser 2016-02-15 21:50:55 +01:00
Carol Willing
161df53143 Merge pull request #426 from takluyver/docs-intro
Add overview to landing page
2016-02-13 11:12:35 -08:00
Thomas Kluyver
1cfd6cf12e Fix grammaros 2016-02-13 18:18:23 +00:00
Thomas Kluyver
d40dcc35fb Reword intro 2016-02-13 16:44:41 +00:00
Thomas Kluyver
a570e95602 Add my overview to intro
Closes gh-425
2016-02-13 15:29:08 +00:00
Thomas Kluyver
e4e43521ee Close code block 2016-02-13 15:28:37 +00:00
Min RK
1b2c21a99c Merge pull request #423 from minrk/custom-logo
allow overriding logo
2016-02-11 15:03:02 +01:00
Min RK
e28eda6386 exercise some static file handlers in tests 2016-02-09 15:38:44 +01:00
Min RK
39c171cce7 allow overriding logo
by specifying JupyterHub.logo_file

also ensures single-user server always has the same logo image as the Hub
2016-02-09 15:38:34 +01:00
Min RK
c81cefd768 Merge pull request #372 from minrk/require-notebook-4
drop support for single-user server from IPython 3.x
2016-02-09 14:42:12 +01:00
Min RK
325f137265 Merge pull request #421 from Fokko/add-docker-label
Added label to dockerfile for referencing
2016-02-09 14:41:48 +01:00
Fokko Driesprong
1ae795df18 Changed domain of the label to .org 2016-02-09 14:16:50 +01:00
Fokko Driesprong
2aacd5e28b Added label to dockerfile for referencing 2016-02-08 17:16:20 +01:00
Kyle Kelley
6e1425e2c0 Merge pull request #417 from minrk/require-confirm-insecure
require confirmation for JupyterHub to run without SSL
2016-02-05 19:27:37 -06:00
Carol Willing
010db6ce72 Merge pull request #416 from willingc/doc-warn
Add more prominent message for https
2016-02-04 14:21:52 -08:00
Min RK
ce8d782220 no-ssl in changelog 2016-02-04 23:00:54 +01:00
Min RK
90c2b23fc0 require confirmation for JupyterHub to run without SSL
ensures folks deploying JupyterHub on HTTP have been told what's up.
2016-02-04 23:00:54 +01:00
Carol Willing
32685aeac1 Add more prominent message for https 2016-02-04 13:42:13 -08:00
Min RK
01c5608104 update version requirements in README 2016-02-04 22:41:18 +01:00
Min RK
a35f6298f0 drop support for single-user server from IPython 3.x 2016-02-04 22:40:44 +01:00
Min RK
8955d6aed4 Merge pull request #411 from minrk/one-two-seven
use 127.0.0.1 instead of localhost
2016-02-04 20:37:09 +01:00
Min RK
cafbf8b990 back to dev 2016-02-03 21:05:48 +01:00
Min RK
7837a9cf68 release 0.4.1 2016-02-03 21:04:32 +01:00
Min RK
65a019e05b Merge pull request #413 from minrk/login_url
Restore /login handler
2016-02-03 21:00:03 +01:00
Min RK
f2014c5687 note that login/logout should always be registered 2016-02-03 20:54:01 +01:00
Min RK
109c315336 changelog for 0.4.1 2016-02-03 16:55:25 +01:00
Min RK
941fc7e627 restore /login page
erroneously removed in 0.4
2016-02-03 16:52:43 +01:00
Min RK
f626d2f6e5 use 127.0.0.1 instead of localhost
localhost can cause some issues on badly behaved or misconfigured systems,
and 127 seems simpler.
2016-02-03 10:30:09 +01:00
Min RK
80215f6b3c Merge pull request #407 from willingc/doc-proxy
Add doc details for #406
2016-02-02 09:06:35 +01:00
Carol Willing
84916062f0 Edit per @minrk and added troubleshooting 2016-02-01 14:17:14 -08:00
Carol Willing
641154bf06 Add doc details for #406 2016-02-01 11:47:08 -08:00
Min RK
14b0dbde0e Merge pull request #405 from willingc/doc-link
Update documentation link to source code
2016-02-01 19:58:08 +01:00
Carol Willing
cd85766441 Update link to source code 2016-02-01 08:42:49 -08:00
Min RK
6c072bdb3d nonempty long_description
avoids dumping README.md garbage onto PyPI
2016-02-01 11:05:58 +01:00
Min RK
35f080458e Upload with twine 2016-02-01 10:41:51 +01:00
Min RK
feac4f6bc4 Changelog for 0.4 2016-02-01 10:41:51 +01:00
Min RK
1bbabbb989 back to dev 2016-02-01 10:37:46 +01:00
Min RK
ad5624c7ce release 0.4.0 2016-02-01 10:37:16 +01:00
Min RK
a7d6c37d26 Merge pull request #400 from willingc/juphub-spawner
Edit tone and grammar in Spawners document
2016-01-29 21:57:51 +01:00
Min RK
b8d9954c28 Merge pull request #402 from mistercrunch/fix_custom_html
Fixing the custom_html feature in the login form
2016-01-29 21:02:45 +01:00
Maxime Beauchemin
927a341764 Fixing the custom_html feature in the login form 2016-01-28 11:25:19 -08:00
Carol Willing
83d092b0ad Minor edit 2016-01-27 22:57:42 -08:00
Carol Willing
95f7889803 Edit the custom spawners doc 2016-01-27 16:48:59 -08:00
Matthias Bussonnier
ceacd72d63 Merge pull request #399 from willingc/newci-badge
Add circleci badge with status only API token
2016-01-25 17:02:29 -08:00
Carol Willing
49c0fa4f08 Add circleci badge with status only API token 2016-01-25 10:56:55 -08:00
Min RK
223318bfff Merge pull request #396 from minrk/test-fixes
If spawner fails to start, show error page
2016-01-25 14:55:07 +01:00
Min RK
9c3f953682 mock pam close session
bug revealed by change in slow_spawn test
2016-01-25 14:29:20 +01:00
Min RK
cc4c65bd0b fix possible loss of port info due to mixed db sessions 2016-01-25 14:28:54 +01:00
Min RK
c4fad21850 If spawner fails to start, show error page
instead of slow-spawner page
2016-01-25 13:32:54 +01:00
Min RK
665907afd3 remove login from default handlers
rely on getting it from LoginHandler
2016-01-25 13:21:21 +01:00
Min RK
8a4305a15c s/chose/choose/ typo 2016-01-25 12:57:19 +01:00
Min RK
7e59148168 ignore node_modules 2016-01-25 12:56:51 +01:00
Min RK
98b44d59c4 Merge pull request #395 from minrk/docker-test
Test docker builds on CircleCI
2016-01-25 12:55:01 +01:00
Min RK
aac357b715 Merge pull request #392 from evanlinde/master
username parameter for notebook_dir
2016-01-25 12:50:47 +01:00
Min RK
2632d03dc2 Merge pull request #391 from minrk/form-error
show error messages on spawn form
2016-01-25 12:46:04 +01:00
Min RK
babb2cf908 test docker builds on circle-ci 2016-01-25 12:32:32 +01:00
Min RK
6a3d790f49 install locale in Dockerfile
and do a little cleanup of temporary installation files
2016-01-25 12:32:32 +01:00
Min RK
9cae91aeb0 Merge pull request #393 from willingc/fix-mdlink
Use relative html link instead of local md
2016-01-22 22:52:01 +01:00
Carol Willing
84f8f8f322 Use relative html link instead of local md 2016-01-22 08:06:30 -08:00
evanlinde
bc4973fb43 username parameter for notebook_dir
Allow specifying user-specific notebook directories outside of user's home folder
2016-01-22 09:47:48 -06:00
Min RK
1a21e822b6 Merge pull request #389 from willingc/fix-docstring
Fix docstrings *ix -> Linux/UNIX to prevent Sphinx build warnings

closes #389
2016-01-22 16:05:31 +01:00
Carol Willing
d437a8f06a Fix docstrings *ix -> Linux/UNIX 2016-01-22 16:05:15 +01:00
Min RK
0555ee44e7 turn on jinja autoescape
now that we are putting user content on the page
2016-01-22 16:02:51 +01:00
Min RK
ef40bd230e Show error messages on spawn form
when spawning fails

instead of 500
2016-01-22 16:02:11 +01:00
Min RK
818510c2ca Merge pull request #381 from minrk/rtd-yml
add preliminary API docs
2016-01-22 12:03:57 +01:00
Min RK
caaab40944 Merge pull request #386 from minrk/dockerfile-jessie
Base Dockerfile on debian:jessie
2016-01-21 13:05:35 +01:00
Min RK
0fb80d43b6 Merge pull request #387 from minrk/single-user-script
make jupyterhub-singleuser a script
2016-01-21 12:55:21 +01:00
Min RK
8146af7240 make jupyterhub-singleuser a script
instead of a module in the package

makes it easier to do `/path/to/python $(which jupyterhub-singleuser)`
2016-01-20 15:41:54 +01:00
Min RK
b9df681115 Merge pull request #353 from minrk/try-localhost
Ensure that we can bind and connect to localhost
2016-01-20 15:37:42 +01:00
Min RK
40a3ebde84 Merge pull request #354 from zoltan-fedor/master
IPv6 ready /etc/hosts file without IPv6 enabled causing localhost issue
2016-01-20 15:37:32 +01:00
Min RK
fbf3b45d52 needs sphinx 1.3 2016-01-20 15:36:26 +01:00
Min RK
eb0a38c136 add preliminary API docs 2016-01-20 15:36:24 +01:00
Min RK
37d42a336f put repo on path
allows autodoc to import jupyterhub without installing it
2016-01-20 15:35:49 +01:00
Min RK
51a04258d1 build on readthedocs 2016-01-20 15:35:49 +01:00
Min RK
1a4226419f Base Dockerfile on debian:jessie
rather than jupyter/notebook

and use conda to get Python 3.5

No longer includes single-user server dependencies
2016-01-20 14:33:39 +01:00
Min RK
ce4cc62c05 Merge pull request #383 from minrk/start-new-session
use start_new_session to detach single-user servers
2016-01-15 17:55:37 +01:00
Min RK
614a0806f5 use start_new_session to detach single-user servers
instead of setpgrp, which causes various problems
2016-01-15 14:21:45 +01:00
Min RK
ff2fef1617 Merge pull request #373 from minrk/normalize-username
Username normalization and validation
2016-01-14 10:16:45 +01:00
Carol Willing
2e6f08268b Merge pull request #380 from minrk/installation
move install commands around a bit
2016-01-13 06:42:36 -08:00
Min RK
ff4019128a move install commands around a bit
npm/less notes are only relevant for dev installs
2016-01-13 15:10:22 +01:00
Min RK
6fd18840a7 Merge pull request #378 from willingc/readme-rtd
Update project README to reflect docs on RTD
2016-01-13 15:07:21 +01:00
Min RK
108d710dcb doc: username normalization and validation 2016-01-13 14:02:51 +01:00
Min RK
aa93384f47 Include system-user creation error message in API reply
when system-user creation fails
2016-01-13 14:02:50 +01:00
Min RK
9441fa37c5 validate usernames
via Authenticator.validate_username

base class configurable with Authenticator.username_pattern
2016-01-13 14:02:50 +01:00
Min RK
beb2dae6ce add username_map 2016-01-13 14:02:50 +01:00
Min RK
887fdaf9d3 add username normalization
Handlers call `get_authenticated_user`, which in turn calls

- authenticate
- normalize_username
- check_whitelist

get_authenticated_user shouldn't need to be overridden.

Normalization can be handled via overriding normalize_username.
2016-01-13 14:02:50 +01:00
Min RK
8a5a85a489 Merge pull request #377 from minrk/swagger-spec
add swagger spec for REST API
2016-01-13 13:08:01 +01:00
Carol Willing
2cc49d317b Add more wording tweaks 2016-01-12 13:55:10 -08:00
Carol Willing
4afa358201 Add some minor formatting 2016-01-12 13:49:04 -08:00
Carol Willing
50a58e5e81 Update README after docs move to RTD 2016-01-12 13:44:08 -08:00
Min RK
479b40d840 add swagger spec for REST API 2016-01-12 16:32:50 +01:00
Min RK
931c2d6f8a Merge pull request #368 from willingc/doc-wip
Sphinx documentation that converts markdown using recommonmark
2016-01-12 16:31:55 +01:00
Min RK
f5746d0765 Merge pull request #375 from betatim/form-file-upload
Handle file upload in spawner form
2016-01-09 23:25:52 +01:00
Tim Head
a59f57e095 Handle file upload in spawner form
Allow files to be uploaded in the spawner form.
2016-01-09 13:53:45 +01:00
Min RK
47549e752d Merge pull request #371 from minrk/delete-user
delete users via UserDict API
2016-01-08 10:32:10 +01:00
Min RK
4534bea86e delete users via UserDict API
avoids reusing user IDs when user creation fails
2016-01-06 15:14:28 +01:00
Carol Willing
2815f72250 Change mocking of slowspawner to match nospawner 2016-01-05 19:45:49 -08:00
Carol Willing
131b695fbb Correct some links 2016-01-05 19:45:49 -08:00
Carol Willing
1bc0d208d3 Move image files 2016-01-05 19:45:49 -08:00
Carol Willing
46a9e8b1c3 Update doc requirements 2016-01-05 19:45:49 -08:00
Carol Willing
04cb5fe503 Add recommonmark parser for markdown 2016-01-05 19:45:49 -08:00
Carol Willing
0ad110f7de Add parsers 2016-01-05 19:45:49 -08:00
Carol Willing
0c5c3eb8b1 Add recommonmark 2016-01-05 19:45:49 -08:00
Carol Willing
bd8b8c55b2 Add initial index file 2016-01-05 19:45:49 -08:00
Carol Willing
e52d2eb27d Add Jupyter customizations 2016-01-05 19:45:49 -08:00
Carol Willing
0b4fbee418 Add sphinx skeleton 2016-01-05 19:45:49 -08:00
Carol Willing
9ee92a3984 Add a requirements for building docs 2016-01-05 19:45:49 -08:00
Carol Willing
f4de573198 Set up docs directory for Sphinx 2016-01-05 19:45:49 -08:00
Min RK
26e00718f9 Merge pull request #366 from minrk/double-redirect
return after redirect to spawner form
2016-01-05 17:19:04 +01:00
Min RK
c878e137aa try codecov for coverage 2016-01-05 14:05:59 +01:00
Min RK
53785a985d return after redirect to spawner form
avoids double-call to redirect, which fails
2016-01-05 14:02:20 +01:00
Min RK
b0cc47984b Merge pull request #364 from minrk/spawn-typo
s/users/user typo in spawn redirect
2015-12-31 17:30:56 +01:00
Min RK
91168fc22b s/users/user typo in spawn redirect 2015-12-31 12:06:04 +01:00
Min RK
66cbb8a614 more testing of spawn page redirects 2015-12-31 12:05:55 +01:00
Min RK
0fbd69be9b Merge pull request #355 from minrk/spawner-options
Add Spawner form page
2015-12-30 16:40:16 +01:00
Min RK
872005f852 document spawner options form 2015-12-30 14:17:58 +01:00
Min RK
647dd09f40 add spawn-form example 2015-12-30 13:55:39 +01:00
Min RK
041c1a4a1e remove always-False else branch 2015-12-30 13:55:38 +01:00
Min RK
d2e3a73f53 set login cookie after starting server
avoids redirect loop
2015-12-30 13:55:38 +01:00
Min RK
2bd7192e89 add extensible get_env hook on Spawner
to make it easier for subclasses to modify the env
2015-12-30 13:55:38 +01:00
Min RK
28f5f33a76 add bootstrap form-control to spawner form inputs 2015-12-30 13:55:38 +01:00
Min RK
f9c9c2b471 options_form is a regular configurable
now that we can assume User.spawner exists at all times
2015-12-30 13:55:38 +01:00
Min RK
41ea696546 Instantiate Spawner on User init
shrinks `User.spawn` to take single argument, grants User more direct access to state.
2015-12-30 13:55:36 +01:00
Min RK
54f9a296de test Spawner.user_options and spawn form 2015-12-30 13:55:01 +01:00
Min RK
ba634354dd Add Spawner form
If Spawner.options_form is specified, a form providing input controls is shown to the user prior to launch.

Spawners access the result via the `self.user_options` dict.

The default spawners offer no form.
2015-12-30 13:55:01 +01:00
Min RK
675f19b5cb Merge pull request #358 from minrk/ipython-traitlets
import base traitlets
2015-12-27 22:26:31 +01:00
Min RK
1eed96193d import base traitlets
missed IPython.utils.traitlets import from old User PR
2015-12-24 12:25:43 +01:00
Zoltan Fedor
faa259e97b IPv6 ready hosts file localhost issue
This is to resolve the 'Network is Unreachable' error experienced by a few when JupyterHUB is connecting to localhost.

On most recent linux OS versions like CentOS 6, 7, Red Hat 6, 7, Oracle Linux 6, 7, etc, the hosts file (/etc/hosts) usually has a line to make the server IPv6-ready:
    ::1 localhost
even if the given server actually has no IPv6 permissioned. In such case the Python socket library when connecting to 'localhost' will try to connect via the IPv6 protocol - which will fail with the 'Network is Unreachable' error.

To solve this we capture this error and try to reconnect on 127.0.0.1 instead of localhost, alias forcing the user of the IPv4 protocol.
2015-12-15 10:53:06 -05:00
Min RK
4785a1ef87 Ensure that we can bind and connect to localhost
otherwise fallback to 127.0.0.1 for defaults
2015-12-15 13:37:30 +01:00
Min RK
aa529f3aba Merge pull request #352 from minrk/sqlalchemy-1.0
require sqlalchemy 1.0
2015-12-14 14:11:52 +01:00
Min RK
98955a5702 require sqlalchemy 1.0
we know 0.7.9 is too old. We might work on 0.8,
but 1.0 is current.
2015-12-14 10:37:48 +01:00
Min RK
2f1a203699 Merge pull request #349 from minrk/adduser
create users with adduser
2015-12-13 13:43:02 +01:00
Brian E. Granger
77b31d8542 Minor fixes to the PR on docs and the default command. 2015-12-13 12:15:31 +01:00
Min RK
8fca4e859d create users with adduser
instead of useradd (on Linux).

- still user `pw useradd` on BSD
- allow complete custom add_user_cmd for specifying directories, etc.
2015-12-13 12:15:31 +01:00
Brian E. Granger
8d90a92ef3 Merge pull request #351 from ellisonbg/token-docs
Edits to the security part of the docs
2015-12-12 15:29:09 -08:00
Brian E. Granger
37424acabf Adding actual secret key... 2015-12-12 15:28:12 -08:00
Brian E. Granger
86a450da77 Edits to the security part of the docs 2015-12-12 14:30:19 -08:00
Min RK
151dcbafb4 Merge pull request #347 from dblockow/feature/log-failed-auth-ip
Log Remote IP Address for Failed Authentication Attempts
2015-12-10 22:51:48 +01:00
David Blockow
d512ee9f65 Fixed to cope with a None handler passed in tests 2015-12-08 15:50:54 +10:30
David Blockow
e59b3f3ab1 Remote IP logged for failed authentication attempts 2015-12-08 15:00:29 +10:30
Min RK
2e7af82865 Merge pull request #185 from minrk/outer-user
move non-persisted User objects (spawner-related) off of orm.User
2015-12-02 12:44:47 +01:00
Min RK
49d4be002b Merge pull request #344 from minrk/system-user-home
add LocalAuthenticator.system_user_home
2015-12-02 10:29:14 +01:00
Min RK
fa8756767d add LocalAuthenticator.system_user_home 2015-12-01 10:36:06 +01:00
Min RK
6f128758db move non-persisted User objects (spawner-related) off of orm.User
adds higher level User object, which handles spawning.
This object has running, spawner, etc. attributes.
2015-11-30 14:05:00 +01:00
Min RK
235746a484 Merge pull request #338 from minrk/dockerfile
install nodejs with one command in Dockerfile
2015-11-25 15:01:57 +01:00
Min RK
37f736cf45 install nodejs with one command in Dockerfile 2015-11-17 14:54:06 +01:00
Min RK
5376291eaa Merge pull request #336 from Fokko/master
Added npm/node which fixes the Dockerfile
2015-11-17 14:52:54 +01:00
Fokko Driesprong
9e738a62d1 Added npm/node which fixes the Dockerfile 2015-11-16 15:55:41 +01:00
Min RK
8bfe52df4f Merge pull request #334 from cwaldbieser/custom_login
Load Authenticator handlers before default handlers
2015-11-10 12:40:57 +01:00
Carl Waldbieser
91ff31f688 Change the order for handlers so that the authenticator handler is added before the default handlers. 2015-11-09 14:17:26 -05:00
Min RK
b7fe3463cf back to dev 2015-11-04 17:13:41 +01:00
Min RK
4931684a2c release 0.3 2015-11-04 17:10:36 +01:00
Min RK
62d3cc53ef changelog for 0.3 2015-11-04 17:09:34 +01:00
Min RK
bd002e5340 Merge pull request #325 from minrk/authenticator-hooks
add pre/post-spawn hooks for Authenticators
2015-11-04 16:07:01 +00:00
Min RK
6f2aefb990 add pre/post-spawn hooks for Authenticators
allows setup/cleanup to be performed by the authenticator

use this to open PAM sessions at spawn
and close them at stop,
rather than open at login and never close.
2015-10-16 12:02:44 +02:00
Min RK
bd3c878c67 Merge pull request #320 from minrk/authenticator-username
get username from authenticator
2015-10-06 15:43:22 +02:00
Min RK
c1de376b6a Merge pull request #310 from minrk/singleuser-notebook
single-user imports notebook package directly
2015-10-06 14:08:35 +02:00
Min RK
4cc74d287e get username from authenticator 2015-10-06 13:36:34 +02:00
Min RK
411a7a0bd8 single-user imports notebook package directly
instead of relying on IPython.html shims

when should we drop support for IPython 3?
2015-09-24 16:13:28 +02:00
Min RK
498c062ee0 Merge pull request #309 from minrk/gen.sleep
use gen.sleep
2015-09-24 16:09:55 +02:00
Min RK
d1edbddb77 use gen.sleep
instead of elaborate `gen.Task(add_timeout...)`

requires tornado 4.1
2015-09-23 17:04:01 +02:00
Min RK
0c9214ffb7 Merge pull request #307 from minrk/test-3.5
test on 3.5
2015-09-22 14:17:30 +02:00
Min RK
db0aaf1027 test on 3.5
requires pytest >= 2.8
2015-09-22 14:09:23 +02:00
Min RK
42681f8512 Merge pull request #306 from minrk/test-token-username
update token app test
2015-09-22 14:08:41 +02:00
Min RK
e5c1414b6a update token app test
now that admin user isn't added by default
2015-09-22 10:14:11 +02:00
Min RK
d857c20de0 Merge pull request #304 from minrk/rm-default-admin
Remove implicit admin of launching user
2015-09-22 08:59:28 +02:00
Min RK
a267174a03 Remove implicit admin of launching user
instead, warn about missing admins and point to config.
2015-09-21 10:52:19 +02:00
Min RK
768eeee470 Merge pull request #298 from minrk/spawner-authenticator
give Spawners a handle on the Authenticator
2015-09-11 14:24:38 +02:00
Min RK
a451f11cd3 give Spawners a handle on the Authenticator
band-aid for spawner-authenticator pairs
2015-09-11 11:57:41 +02:00
Min RK
63a476f9a6 remove some unused cruft from spawner 2015-09-11 11:23:00 +02:00
Min RK
100b17819d Merge pull request #296 from minrk/pamela
use pamela instead of simplepam
2015-09-11 11:02:14 +02:00
Min RK
024d8d7378 update mocking for pamela 2015-09-09 14:24:53 +02:00
Min RK
15e50529ff use pamela instead of simplepam
and open PAM sessions after successful auth
2015-09-09 13:55:02 +02:00
Min RK
a1a10be747 Merge pull request #290 from jhamrick/clear-login-cookies
Unset all login cookies
2015-08-22 18:55:30 -07:00
Jessica B. Hamrick
a91ee67e74 Reset other_user_cookies after clearing them 2015-08-22 13:14:05 -07:00
Jessica B. Hamrick
ea5bfa9999 Unset all login cookies 2015-08-21 19:24:44 -07:00
Min RK
bea58ee622 Merge pull request #288 from minrk/dont-auto-redirect-root
redirect unauthenticated root to *regular* login page
2015-08-19 21:44:00 -07:00
Min RK
b698d4d226 redirect root to *regular* login page
shows "Login with..." button for external services
instead of auto-redirecting to login service
(no good for oauth)
2015-08-19 12:43:32 -07:00
Min RK
139c7ecacb always render login page at /login 2015-08-19 12:30:10 -07:00
Min RK
eefa8fcad7 Merge pull request #284 from minrk/double-base-url
remove double base_url in login redirect
2015-08-06 21:48:49 -07:00
Min RK
acaedcd898 remove double base_url in login redirect
user.server.base_url is already correct,
and shouldn't be joined with the hub url
2015-08-06 21:37:06 -07:00
Min RK
a075661bfb Merge pull request #276 from Crunch-io/redirect-to-login
Redirect unauthenticated root to login
2015-07-23 13:00:16 -07:00
Joseph Tate
f2246df5bb Fix logging and comments 2015-07-23 15:08:53 -04:00
Joseph Tate
1a3c062512 Fix broken test 2015-07-23 15:06:20 -04:00
Joseph Tate
05e4ab41fe Redirect to the loginurl when not logged in, fix the user.running redirect to fix a redirect loop 2015-07-23 15:06:03 -04:00
Min RK
6f3ccb2d3d Merge pull request #275 from jhamrick/installation-instructions
Update installation instructions
2015-07-14 22:06:52 -07:00
Jessica B. Hamrick
6e5ce236c1 Update installation instructions 2015-07-14 15:36:35 -07:00
Min RK
58437057a1 back to dev 2015-07-12 15:30:47 -05:00
190 changed files with 18962 additions and 3176 deletions

View File

@@ -1,4 +1,17 @@
[run]
branch = False
omit =
jupyterhub/tests/*
jupyterhub/singleuser.py
jupyterhub/alembic/*
[report]
exclude_lines =
if self.debug:
pragma: no cover
raise NotImplementedError
if __name__ == .__main__.:
ignore_errors = True
omit =
jupyterhub/tests/*
jupyterhub/alembic/*
*/site-packages/*

View File

@@ -3,3 +3,8 @@ bench
jupyterhub_cookie_secret
jupyterhub.sqlite
jupyterhub_config.py
node_modules
docs
.git
dist
build

25
.flake8 Normal file
View File

@@ -0,0 +1,25 @@
[flake8]
# Ignore style and complexity
# E: style errors
# W: style warnings
# C: complexity
# F401: module imported but unused
# F403: import *
# F811: redefinition of unused `name` from line `N`
# F841: local variable assigned but never used
# E402: module level import not at top of file
# I100: Import statements are in the wrong order
# I101: Imported names are in the wrong order. Should be
ignore = E, C, W, F401, F403, F811, F841, E402, I100, I101
exclude =
.cache,
.github,
docs,
examples,
jupyterhub/alembic*,
onbuild,
scripts,
share,
tools,
setup.py

29
.github/issue_template.md vendored Normal file
View File

@@ -0,0 +1,29 @@
Hi! Thanks for using JupyterHub.
If you are reporting an issue with JupyterHub:
- Please use the [GitHub issue](https://github.com/jupyterhub/jupyterhub/issues)
search feature to check if your issue has been asked already. If it has,
please add your comments to the existing issue.
- Where applicable, please fill out the details below to help us troubleshoot
the issue that you are facing. Please be as thorough as you are able to
provide details on the issue.
**How to reproduce the issue**
**What you expected to happen**
**What actually happens**
**Share what version of JupyterHub you are using**
Running `jupyter troubleshoot` from the command line, if possible, and posting
its output would also be helpful.
```
Insert jupyter troubleshoot output here
```

7
.gitignore vendored
View File

@@ -1,9 +1,14 @@
node_modules
*.py[co]
*~
.cache
.DS_Store
build
/build
dist
docs/_build
docs/build
docs/source/_static/rest-api
.ipynb_checkpoints
# ignore config file at the top-level of the repo
# but not sub-dirs
/jupyterhub_config.py

View File

@@ -1,17 +1,71 @@
# http://travis-ci.org/#!/jupyter/jupyterhub
language: python
sudo: false
cache:
- pip
python:
- 3.4
- 3.3
- nightly
- 3.6
- 3.5
- 3.4
env:
global:
- ASYNC_TEST_TIMEOUT=15
services:
- postgres
- docker
# installing dependencies
before_install:
- npm install
- npm install -g configurable-http-proxy
- git clone --quiet --depth 1 https://github.com/minrk/travis-wheels travis-wheels
- nvm install 6; nvm use 6
- npm install
- npm install -g configurable-http-proxy
- |
if [[ $JUPYTERHUB_TEST_DB_URL == mysql* ]]; then
unset MYSQL_UNIX_PORT
DB=mysql bash ci/docker-db.sh
DB=mysql bash ci/init-db.sh
pip install 'mysql-connector<2.2'
elif [[ $JUPYTERHUB_TEST_DB_URL == postgresql* ]]; then
DB=postgres bash ci/init-db.sh
pip install psycopg2
fi
install:
- pip install -f travis-wheels/wheelhouse -r dev-requirements.txt .
- pip install -f travis-wheels/wheelhouse ipython[notebook]
- pip install -U pip
- pip install --pre -r dev-requirements.txt .
- pip freeze
# running tests
script:
- py.test --cov jupyterhub jupyterhub/tests -v
- |
if [[ ! -z "$JUPYTERHUB_TEST_DB_URL" ]]; then
# if testing upgrade-db, run `jupyterhub token` with 0.7
# to initialize an old db. Used in upgrade-tests
export JUPYTERHUB_TEST_UPGRADE_DB_URL=${JUPYTERHUB_TEST_DB_URL}_upgrade
# use virtualenv instead of venv because venv doesn't work here
python -m pip install virtualenv
python -m virtualenv old-hub-env
./old-hub-env/bin/python -m pip install jupyterhub==0.7.2 psycopg2 'mysql-connector<2.2'
./old-hub-env/bin/jupyterhub token kaylee \
--JupyterHub.db_url=$JUPYTERHUB_TEST_UPGRADE_DB_URL \
--Authenticator.whitelist="{'kaylee'}" \
--JupyterHub.authenticator_class=jupyterhub.auth.Authenticator
fi
- pytest -v --maxfail=2 --cov=jupyterhub jupyterhub/tests
after_success:
- coveralls
- codecov
matrix:
fast_finish: true
include:
- python: 3.6
env: JUPYTERHUB_TEST_SUBDOMAIN_HOST=http://localhost.jovyan.org:8000
- python: 3.6
env:
- MYSQL_HOST=127.0.0.1
- MYSQL_TCP_PORT=13306
- JUPYTERHUB_TEST_DB_URL=mysql+mysqlconnector://root@127.0.0.1:$MYSQL_TCP_PORT/jupyterhub
- python: 3.6
env:
- JUPYTERHUB_TEST_DB_URL=postgresql://postgres@127.0.0.1/jupyterhub
allow_failures:
- python: nightly

26
CHECKLIST-Release.md Normal file
View File

@@ -0,0 +1,26 @@
# Release checklist
- [ ] Upgrade Docs prior to Release
- [ ] Change log
- [ ] New features documented
- [ ] Update the contributor list - thank you page
- [ ] Upgrade and test Reference Deployments
- [ ] Release software
- [ ] Make sure 0 issues in milestone
- [ ] Follow release process steps
- [ ] Send builds to PyPI (Warehouse) and Conda Forge
- [ ] Blog post and/or release note
- [ ] Notify users of release
- [ ] Email Jupyter and Jupyter In Education mailing lists
- [ ] Tweet (optional)
- [ ] Increment the version number for the next release
- [ ] Update roadmap

View File

@@ -1,3 +1,3 @@
# Contributing
We mainly follow the [IPython Contributing Guide](https://github.com/ipython/ipython/blob/master/CONTRIBUTING.md).
Welcome! As a [Jupyter](https://jupyter.org) project, we follow the [Jupyter contributor guide](https://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html).

View File

@@ -1,35 +1,64 @@
# A base docker image that includes juptyerhub and IPython master
# An incomplete base Docker image for running JupyterHub
#
# Build your own derivative images starting with
# Add your configuration to create a complete derivative Docker image.
#
# FROM jupyter/jupyterhub:latest
# Include your configuration settings by starting with one of two options:
#
# Option 1:
#
# FROM jupyterhub/jupyterhub:latest
#
# And put your configuration file jupyterhub_config.py in /srv/jupyterhub/jupyterhub_config.py.
#
# Option 2:
#
# Or you can create your jupyterhub config and database on the host machine, and mount it with:
#
# docker run -v $PWD:/srv/jupyterhub -t jupyterhub/jupyterhub
#
# NOTE
# If you base on jupyterhub/jupyterhub-onbuild
# your jupyterhub_config.py will be added automatically
# from your docker directory.
FROM jupyter/notebook
FROM debian:jessie
MAINTAINER Jupyter Project <jupyter@googlegroups.com>
# install js dependencies
RUN npm install -g configurable-http-proxy
# install nodejs, utf8 locale, set CDN because default httpredir is unreliable
ENV DEBIAN_FRONTEND noninteractive
RUN REPO=http://cdn-fastly.deb.debian.org && \
echo "deb $REPO/debian jessie main\ndeb $REPO/debian-security jessie/updates main" > /etc/apt/sources.list && \
apt-get -y update && \
apt-get -y upgrade && \
apt-get -y install wget locales git bzip2 &&\
/usr/sbin/update-locale LANG=C.UTF-8 && \
locale-gen C.UTF-8 && \
apt-get remove -y locales && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV LANG C.UTF-8
RUN mkdir -p /srv/
# install Python + NodeJS with conda
RUN wget -q https://repo.continuum.io/miniconda/Miniconda3-4.2.12-Linux-x86_64.sh -O /tmp/miniconda.sh && \
echo 'd0c7c71cc5659e54ab51f2005a8d96f3 */tmp/miniconda.sh' | md5sum -c - && \
bash /tmp/miniconda.sh -f -b -p /opt/conda && \
/opt/conda/bin/conda install --yes -c conda-forge \
python=3.5 sqlalchemy tornado jinja2 traitlets requests pip pycurl \
nodejs configurable-http-proxy && \
/opt/conda/bin/pip install --upgrade pip && \
rm /tmp/miniconda.sh
ENV PATH=/opt/conda/bin:$PATH
# install jupyterhub
ADD requirements.txt /tmp/requirements.txt
RUN pip3 install -r /tmp/requirements.txt
ADD . /src/jupyterhub
WORKDIR /src/jupyterhub
WORKDIR /srv/
ADD . /srv/jupyterhub
RUN python setup.py js && pip install . && \
rm -rf $PWD ~/.cache ~/.npm
RUN mkdir -p /srv/jupyterhub/
WORKDIR /srv/jupyterhub/
RUN pip3 install .
WORKDIR /srv/jupyterhub/
# Derivative containers should add jupyterhub config,
# which will be used when starting the application.
EXPOSE 8000
ONBUILD ADD jupyterhub_config.py /srv/jupyterhub/jupyterhub_config.py
CMD ["jupyterhub", "-f", "/srv/jupyterhub/jupyterhub_config.py"]
LABEL org.jupyter.service="jupyterhub"
CMD ["jupyterhub"]

View File

@@ -4,13 +4,18 @@ include setupegg.py
include bower.json
include package.json
include *requirements.txt
include Dockerfile
graft onbuild
graft jupyterhub
graft scripts
graft share
graft singleuser
graft ci
# Documentation
graft docs
prune docs/node_modules
# prune some large unused files from components
prune share/jupyter/hub/static/components/bootstrap/css

288
README.md
View File

@@ -1,129 +1,253 @@
# JupyterHub: A multi-user server for Jupyter notebooks
Questions, comments? Visit our Google Group:
[![Google Group](https://img.shields.io/badge/-Google%20Group-lightgrey.svg)](https://groups.google.com/forum/#!forum/jupyter)
JupyterHub is a multi-user server that manages and proxies multiple instances of the single-user <del>IPython</del> Jupyter notebook server.
Three actors:
- multi-user Hub (tornado process)
- configurable http proxy (node-http-proxy)
- multiple single-user IPython notebook servers (Python/IPython/tornado)
Basic principles:
- Hub spawns proxy
- Proxy forwards ~all requests to hub by default
- Hub handles login, and spawns single-user servers on demand
- Hub configures proxy to forward url prefixes to single-user servers
**[Technical Overview](#technical-overview)** |
**[Installation](#installation)** |
**[Configuration](#configuration)** |
**[Docker](#docker)** |
**[Contributing](#contributing)** |
**[License](#license)** |
**[Help and Resources](#help-and-resources)**
## Dependencies
# [JupyterHub](https://github.com/jupyterhub/jupyterhub)
JupyterHub requires IPython >= 3.0 (current master) and Python >= 3.3.
You will need nodejs/npm, which you can get from your package manager:
[![PyPI](https://img.shields.io/pypi/v/jupyterhub.svg)](https://pypi.python.org/pypi/jupyterhub)
[![Documentation Status](https://readthedocs.org/projects/jupyterhub/badge/?version=latest)](http://jupyterhub.readthedocs.org/en/latest/?badge=latest)
[![Documentation Status](http://readthedocs.org/projects/jupyterhub/badge/?version=0.7.2)](http://jupyterhub.readthedocs.io/en/0.7.2/?badge=0.7.2)
[![Build Status](https://travis-ci.org/jupyterhub/jupyterhub.svg?branch=master)](https://travis-ci.org/jupyterhub/jupyterhub)
[![Circle CI](https://circleci.com/gh/jupyterhub/jupyterhub.svg?style=shield&circle-token=b5b65862eb2617b9a8d39e79340b0a6b816da8cc)](https://circleci.com/gh/jupyterhub/jupyterhub)
[![codecov.io](https://codecov.io/github/jupyterhub/jupyterhub/coverage.svg?branch=master)](https://codecov.io/github/jupyterhub/jupyterhub?branch=master)
[![Google Group](https://img.shields.io/badge/google-group-blue.svg)](https://groups.google.com/forum/#!forum/jupyter)
sudo apt-get install npm nodejs-legacy
With [JupyterHub](https://jupyterhub.readthedocs.io) you can create a
**multi-user Hub** which spawns, manages, and proxies multiple instances of the
single-user [Jupyter notebook (IPython notebook)](https://jupyter-notebook.readthedocs.io)
server.
(The `nodejs-legacy` package installs the `node` executable,
which is required for npm to work on Debian/Ubuntu at this point)
[Project Jupyter](https://jupyter.org) created JupyterHub to support many
users. The Hub can offer notebook servers to a class of students, a corporate
data science workgroup, a scientific research project, or a high performance
computing group.
Then install javascript dependencies:
## Technical overview
sudo npm install -g configurable-http-proxy
Three main actors make up JupyterHub:
### Optional
- multi-user **Hub** (tornado process)
- configurable http **proxy** (node-http-proxy)
- multiple **single-user Jupyter notebook servers** (Python/IPython/tornado)
- Notes on `pip` command used in the below installation sections:
- `sudo` may be needed for `pip install`, depending on filesystem permissions.
- JupyterHub requires Python >= 3.3, so it may be required on some machines to use `pip3` instead
of `pip` (especially when you have both Python 2 and Python 3 installed on your machine).
If `pip3` is not found on your machine, you can get it by doing:
Basic principles for operation are:
sudo apt-get install python3-pip
- Hub spawns a proxy.
- Proxy forwards all requests to Hub by default.
- Hub handles login, and spawns single-user servers on demand.
- Hub configures proxy to forward url prefixes to the single-user notebook
servers.
JupyterHub also provides a
[REST API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/jupyterhub/master/docs/rest-api.yml#/default)
for administration of the Hub and its users.
## Installation
As usual start with cloning the code:
### Check prerequisites
git clone https://github.com/jupyter/jupyterhub.git
cd jupyterhub
A Linux/Unix based system with the following:
Then you can install the Python package by doing:
- [Python](https://www.python.org/downloads/) 3.4 or greater
- [nodejs/npm](https://www.npmjs.com/) Install a recent version of
[nodejs/npm](https://docs.npmjs.com/getting-started/installing-node)
For example, install it on Linux (Debian/Ubuntu) using:
pip3 install -r requirements.txt
pip3 install .
If the `pip3 install .` command fails and complains about `lessc` being unavailable, you may need to explicitly install some additional javascript dependencies:
sudo apt-get install npm nodejs-legacy
npm install
The `nodejs-legacy` package installs the `node` executable and is currently
required for npm to work on Debian/Ubuntu.
If you plan to run notebook servers locally, you may also need to install the IPython notebook:
- TLS certificate and key for HTTPS communication
- Domain name
pip3 install "ipython[notebook]"
### Install packages
JupyterHub can be installed with `pip`, and the proxy with `npm`:
This will fetch client-side javascript dependencies and compile CSS,
and install these files to `sys.prefix`/share/jupyter, as well as
install any Python dependencies.
```bash
npm install -g configurable-http-proxy
pip3 install jupyterhub
```
If you plan to run notebook servers locally, you will need to install the
[Jupyter notebook](https://jupyter.readthedocs.io/en/latest/install.html)
package:
### Development install
pip3 install --upgrade notebook
For a development install:
### Run the Hub server
pip3 install -r dev-requirements.txt -e .
In which case you may need to manually update javascript and css after some updates, with:
python3 setup.py js # fetch updated client-side js (changes rarely)
python3 setup.py css # recompile CSS from LESS sources
## Running the server
To start the server, run the command:
To start the Hub server, run the command:
jupyterhub
and then visit `http://localhost:8000`, and sign in with your unix credentials.
Visit `https://localhost:8000` in your browser, and sign in with your unix
PAM credentials.
If you want multiple users to be able to sign into the server, you will need to run the
`jupyterhub` command as a privileged user, such as root.
The [wiki](https://github.com/jupyter/jupyterhub/wiki/Using-sudo-to-run-JupyterHub-without-root-privileges) describes how to run the server
as a less privileged user, which requires more configuration of the system.
*Note*: To allow multiple users to sign into the server, you will need to
run the `jupyterhub` command as a *privileged user*, such as root.
The [wiki](https://github.com/jupyterhub/jupyterhub/wiki/Using-sudo-to-run-JupyterHub-without-root-privileges)
describes how to run the server as a *less privileged user*, which requires
more configuration of the system.
## Getting started
## Configuration
see the [getting started doc](docs/getting-started.md) for some of the basics of configuring your JupyterHub deployment.
The [Getting Started](http://jupyterhub.readthedocs.io/en/latest/getting-started/index.html) section of the
documentation explains the common steps in setting up JupyterHub.
### Some examples
The [**JupyterHub tutorial**](https://github.com/jupyterhub/jupyterhub-tutorial)
provides an in-depth video and sample configurations of JupyterHub.
generate a default config file:
### Create a configuration file
To generate a default config file with settings and descriptions:
jupyterhub --generate-config
spawn the server on 10.0.1.2:443 with https:
### Start the Hub
To start the Hub on a specific url and port ``10.0.1.2:443`` with **https**:
jupyterhub --ip 10.0.1.2 --port 443 --ssl-key my_ssl.key --ssl-cert my_ssl.cert
The authentication and process spawning mechanisms can be replaced,
which should allow plugging into a variety of authentication or process control environments.
Some examples, meant as illustration and testing of this concept:
### Authenticators
- Using GitHub OAuth instead of PAM with [OAuthenticator](https://github.com/jupyter/oauthenticator)
- Spawning single-user servers with docker, using the [DockerSpawner](https://github.com/jupyter/dockerspawner)
| Authenticator | Description |
| --------------------------------------------------------------------------- | ------------------------------------------------- |
| PAMAuthenticator | Default, built-in authenticator |
| [OAuthenticator](https://github.com/jupyterhub/oauthenticator) | OAuth + JupyterHub Authenticator = OAuthenticator |
| [ldapauthenticator](https://github.com/jupyterhub/ldapauthenticator) | Simple LDAP Authenticator Plugin for JupyterHub |
| [kdcAuthenticator](https://github.com/bloomberg/jupyterhub-kdcauthenticator)| Kerberos Authenticator Plugin for JupyterHub |
# Getting help
### Spawners
We encourage you to ask questions on the mailing list:
| Spawner | Description |
| -------------------------------------------------------------- | -------------------------------------------------------------------------- |
| LocalProcessSpawner | Default, built-in spawner starts single-user servers as local processes |
| [dockerspawner](https://github.com/jupyterhub/dockerspawner) | Spawn single-user servers in Docker containers |
| [kubespawner](https://github.com/jupyterhub/kubespawner) | Kubernetes spawner for JupyterHub |
| [sudospawner](https://github.com/jupyterhub/sudospawner) | Spawn single-user servers without being root |
| [systemdspawner](https://github.com/jupyterhub/systemdspawner) | Spawn single-user notebook servers using systemd |
| [batchspawner](https://github.com/jupyterhub/batchspawner) | Designed for clusters using batch scheduling software |
| [wrapspawner](https://github.com/jupyterhub/wrapspawner) | WrapSpawner and ProfilesSpawner enabling runtime configuration of spawners |
[![Google Group](https://img.shields.io/badge/-Google%20Group-lightgrey.svg)](https://groups.google.com/forum/#!forum/jupyter)
## Docker
but you can participate in development discussions or get live help on Gitter:
A starter [**docker image for JupyterHub**](https://hub.docker.com/r/jupyterhub/jupyterhub/)
gives a baseline deployment of JupyterHub using Docker.
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jupyter/jupyterhub?utm_source=badge&utm_medium=badge)
**Important:** This `jupyterhub/jupyterhub` image contains only the Hub itself,
with no configuration. In general, one needs to make a derivative image, with
at least a `jupyterhub_config.py` setting up an Authenticator and/or a Spawner.
To run the single-user servers, which may be on the same system as the Hub or
not, Jupyter Notebook version 4 or greater must be installed.
The JupyterHub docker image can be started with the following command:
docker run -d --name jupyterhub jupyterhub/jupyterhub jupyterhub
This command will create a container named `jupyterhub` that you can
**stop and resume** with `docker stop/start`.
The Hub service will be listening on all interfaces at port 8000, which makes
this a good choice for **testing JupyterHub on your desktop or laptop**.
If you want to run docker on a computer that has a public IP then you should
(as in MUST) **secure it with ssl** by adding ssl options to your docker
configuration or by using a ssl enabled proxy.
[Mounting volumes](https://docs.docker.com/engine/userguide/containers/dockervolumes/) will
allow you to **store data outside the docker image (host system) so it will be persistent**, even when you start
a new image.
The command `docker exec -it jupyterhub bash` will spawn a root shell in your docker
container. You can **use the root shell to create system users in the container**.
These accounts will be used for authentication in JupyterHub's default configuration.
## Contributing
If you would like to contribute to the project, please read our
[contributor documentation](http://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html)
and the [`CONTRIBUTING.md`](CONTRIBUTING.md).
For a **development install**, clone the [repository](https://github.com/jupyterhub/jupyterhub)
and then install from source:
```bash
git clone https://github.com/jupyterhub/jupyterhub
cd jupyterhub
pip3 install -r dev-requirements.txt -e .
```
If the `pip3 install` command fails and complains about `lessc` being
unavailable, you may need to explicitly install some additional JavaScript
dependencies:
npm install
This will fetch client-side JavaScript dependencies necessary to compile CSS.
You may also need to manually update JavaScript and CSS after some development
updates, with:
```bash
python3 setup.py js # fetch updated client-side js
python3 setup.py css # recompile CSS from LESS sources
```
We use [pytest](http://doc.pytest.org/en/latest/) for **running tests**:
```bash
pytest jupyterhub/tests
```
### A note about platform support
JupyterHub is supported on Linux/Unix based systems.
JupyterHub officially **does not** support Windows. You may be able to use
JupyterHub on Windows if you use a Spawner and Authenticator that work on
Windows, but the JupyterHub defaults will not. Bugs reported on Windows will not
be accepted, and the test suite will not run on Windows. Small patches that fix
minor Windows compatibility issues (such as basic installation) **may** be accepted,
however. For Windows-based systems, we would recommend running JupyterHub in a
docker container or Linux VM.
[Additional Reference:](http://www.tornadoweb.org/en/stable/#installation) Tornado's documentation on Windows platform support
## License
We use a shared copyright model that enables all contributors to maintain the
copyright on their contributions.
All code is licensed under the terms of the revised BSD license.
## Help and resources
We encourage you to ask questions on the [Jupyter mailing list](https://groups.google.com/forum/#!forum/jupyter).
To participate in development discussions or get help, talk with us on
our JupyterHub [Gitter](https://gitter.im/jupyterhub/jupyterhub) channel.
- [Reporting Issues](https://github.com/jupyterhub/jupyterhub/issues)
- [JupyterHub tutorial](https://github.com/jupyterhub/jupyterhub-tutorial)
- [Documentation for JupyterHub](http://jupyterhub.readthedocs.io/en/latest/) | [PDF (latest)](https://media.readthedocs.org/pdf/jupyterhub/latest/jupyterhub.pdf) | [PDF (stable)](https://media.readthedocs.org/pdf/jupyterhub/stable/jupyterhub.pdf)
- [Documentation for JupyterHub's REST API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/jupyterhub/master/docs/rest-api.yml#/default)
- [Documentation for Project Jupyter](http://jupyter.readthedocs.io/en/latest/index.html) | [PDF](https://media.readthedocs.org/pdf/jupyter/latest/jupyter.pdf)
- [Project Jupyter website](https://jupyter.org)
---
**[Technical Overview](#technical-overview)** |
**[Installation](#installation)** |
**[Configuration](#configuration)** |
**[Docker](#docker)** |
**[Contributing](#contributing)** |
**[License](#license)** |
**[Help and Resources](#help-and-resources)**

View File

@@ -2,10 +2,10 @@
"name": "jupyterhub-deps",
"version": "0.0.0",
"dependencies": {
"bootstrap": "components/bootstrap#~3.1",
"font-awesome": "components/font-awesome#~4.1",
"jquery": "components/jquery#~2.0",
"moment": "~2.7",
"requirejs": "~2.1"
"bootstrap": "components/bootstrap#~3.3",
"font-awesome": "components/font-awesome#~4.7",
"jquery": "components/jquery#~3.2",
"moment": "~2.18",
"requirejs": "~2.3"
}
}

50
ci/docker-db.sh Normal file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# source this file to setup postgres and mysql
# for local testing (as similar as possible to docker)
set -e
export MYSQL_HOST=127.0.0.1
export MYSQL_TCP_PORT=${MYSQL_TCP_PORT:-13306}
export PGHOST=127.0.0.1
NAME="hub-test-$DB"
DOCKER_RUN="docker run --rm -d --name $NAME"
docker rm -f "$NAME" 2>/dev/null || true
case "$DB" in
"mysql")
RUN_ARGS="-e MYSQL_ALLOW_EMPTY_PASSWORD=1 -p $MYSQL_TCP_PORT:3306 mysql:5.7"
CHECK="mysql --host $MYSQL_HOST --port $MYSQL_TCP_PORT --user root -e \q"
;;
"postgres")
RUN_ARGS="-p 5432:5432 postgres:9.5"
CHECK="psql --user postgres -c \q"
;;
*)
echo '$DB must be mysql or postgres'
exit 1
esac
$DOCKER_RUN $RUN_ARGS
echo -n "waiting for $DB "
for i in {1..60}; do
if $CHECK; then
echo 'done'
break
else
echo -n '.'
sleep 1
fi
done
$CHECK
echo -e "
Set these environment variables:
export MYSQL_HOST=127.0.0.1
export MYSQL_TCP_PORT=$MYSQL_TCP_PORT
export PGHOST=127.0.0.1
"

27
ci/init-db.sh Normal file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# initialize jupyterhub databases for testing
set -e
MYSQL="mysql --user root --host $MYSQL_HOST --port $MYSQL_TCP_PORT -e "
PSQL="psql --user postgres -c "
case "$DB" in
"mysql")
EXTRA_CREATE='CHARACTER SET utf8 COLLATE utf8_general_ci'
SQL="$MYSQL"
;;
"postgres")
SQL="$PSQL"
;;
*)
echo '$DB must be mysql or postgres'
exit 1
esac
set -x
$SQL 'DROP DATABASE jupyterhub;' 2>/dev/null || true
$SQL "CREATE DATABASE jupyterhub ${EXTRA_CREATE};"
$SQL 'DROP DATABASE jupyterhub_upgrade;' 2>/dev/null || true
$SQL "CREATE DATABASE jupyterhub_upgrade ${EXTRA_CREATE};"

24
circle.yml Normal file
View File

@@ -0,0 +1,24 @@
machine:
services:
- docker
dependencies:
override:
- ls
test:
override:
- docker build -t jupyterhub/jupyterhub .
- docker build -t jupyterhub/jupyterhub-onbuild:${CIRCLE_TAG:-latest} onbuild
deployment:
hub:
branch: master
commands:
- docker login -u $DOCKER_USER -p $DOCKER_PASS -e unused@example.com
- docker push jupyterhub/jupyterhub-onbuild
release:
tag: /.*/
commands:
- docker login -u $DOCKER_USER -p $DOCKER_PASS -e unused@example.com
- docker push jupyterhub/jupyterhub-onbuild:$CIRCLE_TAG

View File

@@ -1,4 +1,9 @@
-r requirements.txt
coveralls
mock
codecov
cryptography
pytest-cov
pytest
pytest-tornado
pytest>=2.8
notebook
requests-mock

206
docs/Makefile Normal file
View File

@@ -0,0 +1,206 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
@echo " spelling to run spell check on documentation"
clean:
rm -rf $(BUILDDIR)/*
node_modules: package.json
npm install && touch node_modules
rest-api: source/_static/rest-api/index.html
source/_static/rest-api/index.html: rest-api.yml node_modules
npm run rest-api
html: rest-api
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/JupyterHub.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/JupyterHub.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/JupyterHub"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/JupyterHub"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
spelling:
$(SPHINXBUILD) -b spelling $(ALLSPHINXOPTS) $(BUILDDIR)/spelling
@echo
@echo "Spell check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/spelling/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

View File

@@ -1,80 +0,0 @@
# Writing a custom Authenticator
The [Authenticator][] is the mechanism for authorizing users.
Basic authenticators use simple username and password authentication.
JupyterHub ships only with a [PAM][]-based Authenticator,
for logging in with local user accounts.
You can use custom Authenticator subclasses to enable authentication via other systems.
One such example is using [GitHub OAuth][].
Because the username is passed from the Authenticator to the Spawner,
a custom Authenticator and Spawner are often used together.
See a list of custom Authenticators [on the wiki](https://github.com/jupyter/jupyterhub/wiki/Authenticators).
## Basics of Authenticators
A basic Authenticator has one central method:
### Authenticator.authenticate
Authenticator.authenticate(handler, data)
This method is passed the tornado RequestHandler and the POST data from the login form.
Unless the login form has been customized, `data` will have two keys:
- `username` (self-explanatory)
- `password` (also self-explanatory)
`authenticate`'s job is simple:
- return a username (non-empty str)
of the authenticated user if authentication is successful
- return `None` otherwise
Writing an Authenticator that looks up passwords in a dictionary
requires only overriding this one method:
```python
from tornado import gen
from IPython.utils.traitlets import Dict
from jupyterhub.auth import Authenticator
class DictionaryAuthenticator(Authenticator):
passwords = Dict(config=True,
help="""dict of username:password for authentication"""
)
@gen.coroutine
def authenticate(self, handler, data):
if self.passwords.get(data['username']) == data['password']:
return data['username']
```
### Authenticator.whitelist
Authenticators can specify a whitelist of usernames to allow authentication.
For local user authentication (e.g. PAM), this lets you limit which users
can login.
## OAuth and other non-password logins
Some login mechanisms, such as [OAuth][], don't map onto username+password.
For these, you can override the login handlers.
You can see an example implementation of an Authenticator that uses [GitHub OAuth][]
at [OAuthenticator][].
[Authenticator]: ../jupyterhub/auth.py
[PAM]: http://en.wikipedia.org/wiki/Pluggable_authentication_module
[OAuth]: http://en.wikipedia.org/wiki/OAuth
[GitHub OAuth]: https://developer.github.com/v3/oauth/
[OAuthenticator]: https://github.com/jupyter/oauthenticator

19
docs/environment.yml Normal file
View File

@@ -0,0 +1,19 @@
name: jhub_docs
channels:
- conda-forge
dependencies:
- nodejs
- python=3.5
- alembic
- jinja2
- pamela
- requests
- sqlalchemy>=1
- tornado>=4.1
- traitlets>=4.1
- sphinx>=1.4, !=1.5.4
- sphinx_rtd_theme
- pip:
- jupyter_alabaster_theme
- python-oauth2
- recommonmark==0.4.0

View File

@@ -1,389 +0,0 @@
# Getting started with JupyterHub
This document describes some of the basics of configuring JupyterHub to do what you want.
JupyterHub is highly customizable, so there's a lot to cover.
## Installation
See [the readme](../README.md) for help installing JupyterHub.
## Overview
JupyterHub is a set of processes that together provide a multiuser Jupyter Notebook server.
There are three main categories of processes run by the `jupyterhub` command line program:
- *Single User Server*: a dedicated, single-user, Jupyter Notebook is started for each user on the system
when they log in. The object that starts these processes is called a *Spawner*.
- *Proxy*: the public facing part of the server that uses a dynamic proxy to route HTTP requests
to the *Hub* and *Single User Servers*.
- *Hub*: manages user accounts and authentication and coordinates *Single Users Servers* using a *Spawner*.
## JupyterHub's default behavior
To start JupyterHub in its default configuration, type the following at the command line:
sudo jupyterhub
The default Authenticator that ships with JupyterHub authenticates users
with their system name and password (via [PAM][]).
Any user on the system with a password will be allowed to start a single-user notebook server.
The default Spawner starts servers locally as each user, one dedicated server per user.
These servers listen on localhost, and start in the given user's home directory.
By default, the *Proxy* listens on all public interfaces on port 8000.
Thus you can reach JupyterHub through:
http://localhost:8000
or any other public IP or domain pointing to your system.
In their default configuration, the other services, the *Hub* and *Single-User Servers*,
all communicate with each other on localhost only.
**NOTE:** In its default configuration, JupyterHub runs without SSL encryption (HTTPS).
You should not run JupyterHub without SSL encryption on a public network.
See [below](#Security) for how to configure JupyterHub to use SSL.
By default, starting JupyterHub will write two files to disk in the current working directory:
- `jupyterhub.sqlite` is the sqlite database containing all of the state of the *Hub*.
This file allows the *Hub* to remember what users are running and where,
as well as other information enabling you to restart parts of JupyterHub separately.
- `jupyterhub_cookie_secret` is the encryption key used for securing cookies.
This file needs to persist in order for restarting the Hub server to avoid invalidating cookies.
Conversely, deleting this file and restarting the server effectively invalidates all login cookies.
The cookie secret file is discussed [below](#Security).
The location of these files can be specified via configuration, discussed below.
## How to configure JupyterHub
JupyterHub is configured in two ways:
1. Command-line arguments
2. Configuration files
Type the following for brief information about the command line arguments:
jupyterhub -h
or:
jupyterhub --help-all
for the full command line help.
By default, JupyterHub will look for a configuration file (can be missing)
named `jupyterhub_config.py` in the current working directory.
You can create an empty configuration file with
jupyterhub --generate-config
This empty configuration file has descriptions of all configuration variables and their default values.
You can load a specific config file with:
jupyterhub -f /path/to/jupyterhub_config.py
See also: [general docs](http://ipython.org/ipython-doc/dev/development/config.html)
on the config system Jupyter uses.
## Networking
In most situations you will want to change the main IP address and port of the Proxy.
This address determines where JupyterHub is available to your users.
The default is all network interfaces (`''`) on port 8000.
This can be done with the following command line arguments:
jupyterhub --ip=192.168.1.2 --port=443
Or you can put the following lines in a configuration file:
```python
c.JupyterHub.ip = '192.168.1.2'
c.JupyterHub.port = 443
```
Port 443 is used in these examples as it is the default port for SSL/HTTPS.
Configuring only the main IP and port of JupyterHub should be sufficient for most deployments of JupyterHub.
However, for more customized scenarios,
you can configure the following additional networking details.
The Hub service talks to the proxy via a REST API on a secondary port,
whose network interface and port can be configured separately.
By default, this REST API listens on port 8081 of localhost only.
If you want to run the Proxy separate from the Hub,
you may need to configure this IP and port with:
```python
# ideally a private network address
c.JupyterHub.proxy_api_ip = '10.0.1.4'
c.JupyterHub.proxy_api_port = 5432
```
The Hub service also listens only on localhost (port 8080) by default.
The Hub needs needs to be accessible from both the proxy and all Spawners.
When spawning local servers localhost is fine,
but if *either* the Proxy or (more likely) the Spawners will be remote or isolated in containers,
the Hub must listen on an IP that is accessible.
```python
c.JupyterHub.hub_ip = '10.0.1.4'
c.JupyterHub.hub_port = 54321
```
## Security
First of all, since JupyterHub includes authentication and allows arbitrary code execution,
you should not run it without SSL (HTTPS).
This will require you to obtain an official SSL certificate or create a self-signed certificate.
Once you have obtained and installed a key and certificate
you need to pass their locations to JupyterHub's configuration as follows:
```python
c.JupyterHub.ssl_key = '/path/to/my.key'
c.JupyterHub.ssl_cert = '/path/to/my.cert'
```
Some cert files also contain the key, in which case only the cert is needed.
It is important that these files be put in a secure location on your server.
There are two other aspects of JupyterHub network security.
The cookie secret is an encryption key, used to encrypt the cookies used for authentication.
If this value changes for the Hub,
all single-user servers must also be restarted.
Normally, this value is stored in the file `jupyterhub_cookie_secret`,
which can be specified with:
```python
c.JupyterHub.cookie_secret_file = '/path/to/jupyterhub_cookie_secret'
```
In most deployments of JupyterHub, you should point this to a secure location on the file system.
If the cookie secret file doesn't exist when the Hub starts,
a new cookie secret is generated and stored in the file.
If you would like to avoid the need for files,
the value can be loaded in the Hub process from the `JPY_COOKIE_SECRET` env variable:
```bash
export JPY_COOKIE_SECRET=`openssl rand -hex 1024`
```
For security reasons, this env variable should only be visible to the Hub.
The Hub authenticates its requests to the Proxy via an environment variable, `CONFIGPROXY_AUTH_TOKEN`.
If you want to be able to start or restart the proxy or Hub independently of each other (not always necessary),
you must set this environment variable before starting the server (for both the Hub and Proxy):
```bash
export CONFIGPROXY_AUTH_TOKEN=`openssl rand -hex 32`
```
This env variable needs to be visible to the Hub and Proxy.
If you don't set this, the Hub will generate a random key itself,
which means that any time you restart the Hub you **must also restart the Proxy**.
If the proxy is a subprocess of the Hub,
this should happen automatically (this is the default configuration).
## Configuring Authentication
The default Authenticator uses [PAM][] to authenticate system users with their username and password.
The default behavior of this Authenticator is to allow any user with an account and password on the system to login.
You can restrict which users are allowed to login with `Authenticator.whitelist`:
```python
c.Authenticator.whitelist = {'mal', 'zoe', 'inara', 'kaylee'}
```
Admin users of JupyterHub have the ability to take actions on users' behalf,
such as stopping and restarting their servers,
and adding and removing new users from the whitelist.
Any users in the admin list are automatically added to the whitelist,
if they are not already present.
The set of initial Admin users can configured as follows:
```python
c.Authenticator.admin_users = {'mal', 'zoe'}
```
If `JupyterHub.admin_access` is True (not default),
then admin users have permission to log in *as other users* on their respective machines, for debugging.
**You should make sure your users know if admin_access is enabled.**
### Adding and removing users
Users can be added and removed to the Hub via the admin panel or REST API.
These users will be added to the whitelist and database.
Restarting the Hub will not require manually updating the whitelist in your config file,
as the users will be loaded from the database.
This means that after starting the Hub once,
it is not sufficient to remove users from the whitelist in your config file.
You must also remove them from the database, either by discarding the database file,
or via the admin UI.
The default PAMAuthenticator is one case of a special kind of authenticator,
called a LocalAuthenticator,
indicating that it manages users on the local system.
When you add a user to the Hub, a LocalAuthenticator checks if that user already exists.
Normally, there will be an error telling you that the user doesn't exist.
If you set the configuration value
```python
c.LocalAuthenticator.create_system_users = True
```
however, adding a user to the Hub that doesn't already exist on the system
will result in the Hub creating that user via the system `useradd` mechanism.
This option is typically used on hosted deployments of JupyterHub,
to avoid the need to manually create all your users before launching the service.
It is not recommended when running JupyterHub in situations where JupyterHub users maps directly onto UNIX users.
## Configuring single-user servers
Since the single-user server is an instance of `ipython notebook`,
an entire separate multi-process application,
there are many aspect of that server can configure,
and a lot of ways to express that configuration.
At the JupyterHub level, you can set some values on the Spawner.
The simplest of these is `Spawner.notebook_dir`,
which lets you set the root directory for a user's server.
This root notebook directory is the highest level directory users will be able to access in the notebook dashboard.
In this example, the root notebook directory is set to `~/notebooks`,
where `~` is expanded to the user's home directory.
```python
c.Spawner.notebook_dir = '~/notebooks'
```
You can also specify extra command-line arguments to the notebook server with:
```python
c.Spawner.args = ['--debug', '--profile=PHYS131']
```
This could be used to set the users default page for the single user server:
```python
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
```
Since the single-user server extends the notebook server application,
it still loads configuration from the `ipython_notebook_config.py` config file.
Each user may have one of these files in `$HOME/.ipython/profile_default/`.
IPython also supports loading system-wide config files from `/etc/ipython/`,
which is the place to put configuration that you want to affect all of your users.
## External services
JupyterHub has a REST API that can be used to run external services.
More detail on this API will be added in the future.
## File locations
It is recommended to put all of the files used by JupyterHub into standard UNIX filesystem locations.
* `/srv/jupyterhub` for all security and runtime files
* `/etc/jupyterhub` for all configuration files
* `/var/log` for log files
## Example
In the following example, we show a configuration files for a fairly standard JupyterHub deployment with the following assumptions:
* JupyterHub is running on a single cloud server
* Using SSL on the standard HTTPS port 443
* You want to use [GitHub OAuth][oauthenticator] for login
* You need the users to exist locally on the server
* You want users' notebooks to be served from `~/assignments` to allow users to browse for notebooks within
other users home directories
* You want the landing page for each user to be a Welcome.ipynb notebook in their assignments directory.
* All runtime files are put into `/srv/jupyterhub` and log files in `/var/log`.
Let's start out with `jupyterhub_config.py`:
```python
# jupyterhub_config.py
c = get_config()
import os
pjoin = os.path.join
runtime_dir = os.path.join('/srv/jupyterhub')
ssl_dir = pjoin(runtime_dir, 'ssl')
if not os.path.exists(ssl_dir):
os.makedirs(ssl_dir)
# https on :443
c.JupyterHub.port = 443
c.JupyterHub.ssl_key = pjoin(ssl_dir, 'ssl.key')
c.JupyterHub.ssl_cert = pjoin(ssl_dir, 'ssl.cert')
# put the JupyterHub cookie secret and state db
# in /var/run/jupyterhub
c.JupyterHub.cookie_secret_file = pjoin(runtime_dir, 'cookie_secret')
c.JupyterHub.db_url = pjoin(runtime_dir, 'jupyterhub.sqlite')
# or `--db=/path/to/jupyterhub.sqlite` on the command-line
# put the log file in /var/log
c.JupyterHub.log_file = '/var/log/jupyterhub.log'
# use GitHub OAuthenticator for local users
c.JupyterHub.authenticator_class = 'oauthenticator.LocalGitHubOAuthenticator'
c.GitHubOAuthenticator.oauth_callback_url = os.environ['OAUTH_CALLBACK_URL']
# create system users that don't exist yet
c.LocalAuthenticator.create_system_users = True
# specify users and admin
c.Authenticator.whitelist = {'rgbkrk', 'minrk', 'jhamrick'}
c.Authenticator.admin_users = {'jhamrick', 'rgbkrk'}
# start single-user notebook servers in ~/assignments,
# with ~/assignments/Welcome.ipynb as the default landing page
# this config could also be put in
# /etc/ipython/ipython_notebook_config.py
c.Spawner.notebook_dir = '~/assignments'
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
```
Using the GitHub Authenticator [requires a few additional env variables][oauth-setup],
which we will need to set when we launch the server:
```bash
export GITHUB_CLIENT_ID=github_id
export GITHUB_CLIENT_SECRET=github_secret
export OAUTH_CALLBACK_URL=https://example.com/hub/oauth_callback
export CONFIGPROXY_AUTH_TOKEN=super-secret
jupyterhub -f /path/to/aboveconfig.py
```
# Further reading
- TODO: troubleshooting
- [Custom Authenticators](authenticators.md)
- [Custom Spawners](spawners.md)
[oauth-setup]: https://github.com/jupyter/oauthenticator#setup
[oauthenticator]: https://github.com/jupyter/oauthenticator
[PAM]: http://en.wikipedia.org/wiki/Pluggable_authentication_module

View File

@@ -1,77 +0,0 @@
# How JupyterHub works
JupyterHub is a multi-user server that manages and proxies multiple instances of the single-user <del>IPython</del> Jupyter notebook server.
There are three basic processes involved:
- multi-user Hub (Python/Tornado)
- configurable http proxy (nodejs)
- multiple single-user IPython notebook servers (Python/IPython/Tornado)
The proxy is the only process that listens on a public interface.
The Hub sits behind the proxy at `/hub`.
Single-user servers sit behind the proxy at `/user/[username]`.
## Logging in
When a new browser logs in to JupyterHub, the following events take place:
- Login data is handed to the [Authenticator](#authentication) instance for validation
- The Authenticator returns the username, if login information is valid
- A single-user server instance is [Spawned](#spawning) for the logged-in user
- When the server starts, the proxy is notified to forward `/user/[username]/*` to the single-user server
- Two cookies are set, one for `/hub/` and another for `/user/[username]`,
containing an encrypted token.
- The browser is redirected to `/user/[username]`, which is handled by the single-user server
Logging into a single-user server is authenticated via the Hub:
- On request, the single-user server forwards the encrypted cookie to the Hub for verification
- The Hub replies with the username if it is a valid cookie
- If the user is the owner of the server, access is allowed
- If it is the wrong user or an invalid cookie, the browser is redirected to `/hub/login`
## Customizing JupyterHub
There are two basic extension points for JupyterHub: How users are authenticated,
and how their server processes are started.
Each is governed by a customizable class,
and JupyterHub ships with just the most basic version of each.
To enable custom authentication and/or spawning,
subclass Authenticator or Spawner,
and override the relevant methods.
### Authentication
Authentication is customizable via the Authenticator class.
Authentication can be replaced by any mechanism,
such as OAuth, Kerberos, etc.
JupyterHub only ships with [PAM](http://en.wikipedia.org/wiki/Pluggable_authentication_module) authentication,
which requires the server to be run as root,
or at least with access to the PAM service,
which regular users typically do not have
(on Ubuntu, this requires being added to the `shadow` group).
[More info on custom Authenticators](authenticators.md).
See a list of custom Authenticators [on the wiki](https://github.com/jupyter/jupyterhub/wiki/Authenticators).
### Spawning
Each single-user server is started by a Spawner.
The Spawner represents an abstract interface to a process,
and needs to be able to take three actions:
1. start the process
2. poll whether the process is still running
3. stop the process
[More info on custom Spawners](spawners.md).
See a list of custom Spawners [on the wiki](https://github.com/jupyter/jupyterhub/wiki/Spawners).

263
docs/make.bat Normal file
View File

@@ -0,0 +1,263 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
set I18NSPHINXOPTS=%SPHINXOPTS% source
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
echo. coverage to run coverage check of the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
REM Check if sphinx-build is available and fallback to Python version if any
%SPHINXBUILD% 1>NUL 2>NUL
if errorlevel 9009 goto sphinx_python
goto sphinx_ok
:sphinx_python
set SPHINXBUILD=python -m sphinx.__init__
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
:sphinx_ok
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\JupyterHub.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\JupyterHub.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "coverage" (
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
if errorlevel 1 exit /b 1
echo.
echo.Testing of coverage in the sources finished, look at the ^
results in %BUILDDIR%/coverage/python.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end

14
docs/package.json Normal file
View File

@@ -0,0 +1,14 @@
{
"name": "jupyterhub-docs-build",
"version": "0.8.0",
"description": "build JupyterHub swagger docs",
"scripts": {
"rest-api": "bootprint openapi ./rest-api.yml source/_static/rest-api"
},
"author": "",
"license": "BSD-3-Clause",
"devDependencies": {
"bootprint": "^1.0.0",
"bootprint-openapi": "^1.0.0"
}
}

3
docs/requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
-r ../requirements.txt
sphinx>=1.4
recommonmark==0.4.0

630
docs/rest-api.yml Normal file
View File

@@ -0,0 +1,630 @@
# see me at: http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/jupyterhub/master/docs/rest-api.yml#/default
swagger: '2.0'
info:
title: JupyterHub
description: The REST API for JupyterHub
version: 0.8.0dev
license:
name: BSD-3-Clause
schemes:
- [http, https]
securityDefinitions:
token:
type: apiKey
name: Authorization
in: header
security:
- token: []
basePath: /hub/api
produces:
- application/json
consumes:
- application/json
paths:
/:
get:
summary: Get JupyterHub version
description: |
This endpoint is not authenticated for the purpose of clients and user
to identify the JupyterHub version before setting up authentication.
responses:
'200':
description: The JupyterHub version
schema:
type: object
properties:
version:
type: string
description: The version of JupyterHub itself
/info:
get:
summary: Get detailed info about JupyterHub
description: |
Detailed JupyterHub information, including Python version,
JupyterHub's version and executable path,
and which Authenticator and Spawner are active.
responses:
'200':
description: Detailed JupyterHub info
schema:
type: object
properties:
version:
type: string
description: The version of JupyterHub itself
python:
type: string
description: The Python version, as returned by sys.version
sys_executable:
type: string
description: The path to sys.executable running JupyterHub
authenticator:
type: object
properties:
class:
type: string
description: The Python class currently active for JupyterHub Authentication
version:
type: string
description: The version of the currently active Authenticator
spawner:
type: object
properties:
class:
type: string
description: The Python class currently active for spawning single-user notebook servers
version:
type: string
description: The version of the currently active Spawner
/users:
get:
summary: List users
responses:
'200':
description: The Hub's user list
schema:
type: array
items:
$ref: '#/definitions/User'
post:
summary: Create multiple users
parameters:
- name: data
in: body
required: true
schema:
type: object
properties:
usernames:
type: array
description: list of usernames to create on the Hub
items:
type: string
admin:
description: whether the created users should be admins
type: boolean
responses:
'201':
description: The users have been created
schema:
type: array
description: The created users
items:
$ref: '#/definitions/User'
/users/{name}:
get:
summary: Get a user by name
parameters:
- name: name
description: username
in: path
required: true
type: string
responses:
'200':
description: The User model
schema:
$ref: '#/definitions/User'
post:
summary: Create a single user
parameters:
- name: name
description: username
in: path
required: true
type: string
responses:
'201':
description: The user has been created
schema:
$ref: '#/definitions/User'
patch:
summary: Modify a user
description: Change a user's name or admin status
parameters:
- name: name
description: username
in: path
required: true
type: string
- name: data
in: body
required: true
description: Updated user info. At least one key to be updated (name or admin) is required.
schema:
type: object
properties:
name:
type: string
description: the new name (optional, if another key is updated i.e. admin)
admin:
type: boolean
description: update admin (optional, if another key is updated i.e. name)
responses:
'200':
description: The updated user info
schema:
$ref: '#/definitions/User'
delete:
summary: Delete a user
parameters:
- name: name
description: username
in: path
required: true
type: string
responses:
'204':
description: The user has been deleted
/users/{name}/server:
post:
summary: Start a user's single-user notebook server
parameters:
- name: name
description: username
in: path
required: true
type: string
responses:
'201':
description: The user's notebook server has started
'202':
description: The user's notebook server has not yet started, but has been requested
delete:
summary: Stop a user's server
parameters:
- name: name
description: username
in: path
required: true
type: string
responses:
'204':
description: The user's notebook server has stopped
'202':
description: The user's notebook server has not yet stopped as it is taking a while to stop
/users/{name}/servers/{server_name}:
post:
summary: Start a user's single-user named-server notebook server
parameters:
- name: name
description: username
in: path
required: true
type: string
- name: server_name
description: name given to a named-server
in: path
required: true
type: string
responses:
'201':
description: The user's notebook named-server has started
'202':
description: The user's notebook named-server has not yet started, but has been requested
delete:
summary: Stop a user's named-server
parameters:
- name: name
description: username
in: path
required: true
type: string
- name: server_name
description: name given to a named-server
in: path
required: true
type: string
responses:
'204':
description: The user's notebook named-server has stopped
'202':
description: The user's notebook named-server has not yet stopped as it is taking a while to stop
/users/{name}/admin-access:
post:
summary: Grant admin access to this user's notebook server
parameters:
- name: name
description: username
in: path
required: true
type: string
responses:
'200':
description: Sets a cookie granting the requesting administrator access to the user's notebook server
/user:
summary: Return authenticated user's model
description:
parameters:
responses:
'200':
description: The authenticated user's model is returned.
/groups:
get:
summary: List groups
responses:
'200':
description: The list of groups
schema:
type: array
items:
$ref: '#/definitions/Group'
/groups/{name}:
get:
summary: Get a group by name
parameters:
- name: name
description: group name
in: path
required: true
type: string
responses:
'200':
description: The group model
schema:
$ref: '#/definitions/Group'
post:
summary: Create a group
parameters:
- name: name
description: group name
in: path
required: true
type: string
responses:
'201':
description: The group has been created
schema:
$ref: '#/definitions/Group'
delete:
summary: Delete a group
parameters:
- name: name
description: group name
in: path
required: true
type: string
responses:
'204':
description: The group has been deleted
/groups/{name}/users:
post:
summary: Add users to a group
parameters:
- name: name
description: group name
in: path
required: true
type: string
- name: data
in: body
required: true
description: The users to add to the group
schema:
type: object
properties:
users:
type: array
description: List of usernames to add to the group
items:
type: string
responses:
'200':
description: The users have been added to the group
schema:
$ref: '#/definitions/Group'
delete:
summary: Remove users from a group
parameters:
- name: name
description: group name
in: path
required: true
type: string
- name: data
in: body
required: true
description: The users to remove from the group
schema:
type: object
properties:
users:
type: array
description: List of usernames to remove from the group
items:
type: string
responses:
'200':
description: The users have been removed from the group
/services:
get:
summary: List services
responses:
'200':
description: The service list
schema:
type: array
items:
$ref: '#/definitions/Service'
/services/{name}:
get:
summary: Get a service by name
parameters:
- name: name
description: service name
in: path
required: true
type: string
responses:
'200':
description: The Service model
schema:
$ref: '#/definitions/Service'
/proxy:
get:
summary: Get the proxy's routing table
description: A convenience alias for getting the routing table directly from the proxy
responses:
'200':
description: Routing table
schema:
type: object
description: configurable-http-proxy routing table (see configurable-http-proxy docs for details)
post:
summary: Force the Hub to sync with the proxy
responses:
'200':
description: Success
patch:
summary: Notify the Hub about a new proxy
description: Notifies the Hub of a new proxy to use.
parameters:
- name: data
in: body
required: true
description: Any values that have changed for the new proxy. All keys are optional.
schema:
type: object
properties:
ip:
type: string
description: IP address of the new proxy
port:
type: string
description: Port of the new proxy
protocol:
type: string
description: Protocol of new proxy, if changed
auth_token:
type: string
description: CONFIGPROXY_AUTH_TOKEN for the new proxy
responses:
'200':
description: Success
/authorizations/token:
post:
summary: Request a new API token
description: |
Request a new API token to use with the JupyterHub REST API.
If not already authenticated, username and password can be sent
in the JSON request body.
Logging in via this method is only available when the active Authenticator
accepts passwords (e.g. not OAuth).
parameters:
- name: username
in: body
required: false
type: string
- name: password
in: body
required: false
type: string
responses:
'200':
description: The new API token
schema:
type: object
properties:
token:
type: string
description: The new API token.
'403':
description: The user can not be authenticated.
/authorizations/token/{token}:
get:
summary: Identify a user or service from an API token
parameters:
- name: token
in: path
required: true
type: string
responses:
'200':
description: The user or service identified by the API token
'404':
description: A user or service is not found.
/authorizations/cookie/{cookie_name}/{cookie_value}:
get:
summary: Identify a user from a cookie
description: Used by single-user notebook servers to hand off cookie authentication to the Hub
parameters:
- name: cookie_name
in: path
required: true
type: string
- name: cookie_value
in: path
required: true
type: string
responses:
'200':
description: The user identified by the cookie
schema:
$ref: '#/definitions/User'
'404':
description: A user is not found.
/oauth2/authorize:
get:
summary: 'OAuth 2.0 authorize endpoint'
description: |
Redirect users to this URL to begin the OAuth process.
It is not an API endpoint.
parameters:
- name: client_id
description: The client id
in: query
required: true
type: string
- name: response_type
description: The response type (always 'code')
in: query
required: true
type: string
- name: state
description: A state string
in: query
required: false
type: string
- name: redirect_uri
description: The redirect url
in: query
required: true
type: string
/oauth2/token:
post:
summary: Request an OAuth2 token
description: |
Request an OAuth2 token from an authorization code.
This request completes the OAuth process.
consumes:
- application/x-www-form-urlencoded
parameters:
- name: client_id
description: The client id
in: form
required: true
type: string
- name: client_secret
description: The client secret
in: form
required: true
type: string
- name: grant_type
description: The grant type (always 'authorization_code')
in: form
required: true
type: string
- name: code
description: The code provided by the authorization redirect
in: form
required: true
type: string
- name: redirect_uri
description: The redirect url
in: form
required: true
type: string
responses:
'200':
description: JSON response including the token
schema:
type: object
properties:
access_token:
type: string
description: The new API token for the user
token_type:
type: string
description: Will always be 'Bearer'
/shutdown:
post:
summary: Shutdown the Hub
parameters:
- name: proxy
in: body
type: boolean
description: Whether the proxy should be shutdown as well (default from Hub config)
- name: servers
in: body
type: boolean
description: Whether users' notebook servers should be shutdown as well (default from Hub config)
definitions:
User:
type: object
properties:
name:
type: string
description: The user's name
admin:
type: boolean
description: Whether the user is an admin
groups:
type: array
description: The names of groups where this user is a member
items:
type: string
server:
type: string
description: The user's notebook server's base URL, if running; null if not.
pending:
type: string
enum: ["spawn", "stop"]
description: The currently pending action, if any
last_activity:
type: string
format: date-time
description: Timestamp of last-seen activity from the user
Group:
type: object
properties:
name:
type: string
description: The group's name
users:
type: array
description: The names of users who are members of this group
items:
type: string
Service:
type: object
properties:
name:
type: string
description: The service's name
admin:
type: boolean
description: Whether the service is an admin
url:
type: string
description: The internal url where the service is running
prefix:
type: string
description: The proxied URL prefix to the service's url
pid:
type: number
description: The PID of the service process (if managed)
command:
type: array
description: The command used to start the service (if managed)
items:
type: string

16
docs/source/api/app.rst Normal file
View File

@@ -0,0 +1,16 @@
=========================
Application configuration
=========================
Module: :mod:`jupyterhub.app`
=============================
.. automodule:: jupyterhub.app
.. currentmodule:: jupyterhub.app
:class:`JupyterHub`
-------------------
.. autoconfigurable:: JupyterHub

28
docs/source/api/auth.rst Normal file
View File

@@ -0,0 +1,28 @@
==============
Authenticators
==============
Module: :mod:`jupyterhub.auth`
==============================
.. automodule:: jupyterhub.auth
.. currentmodule:: jupyterhub.auth
:class:`Authenticator`
----------------------
.. autoconfigurable:: Authenticator
:members:
:class:`LocalAuthenticator`
---------------------------
.. autoconfigurable:: LocalAuthenticator
:members:
:class:`PAMAuthenticator`
-------------------------
.. autoconfigurable:: PAMAuthenticator

38
docs/source/api/index.rst Normal file
View File

@@ -0,0 +1,38 @@
.. _api-index:
##################
The JupyterHub API
##################
:Release: |release|
:Date: |today|
JupyterHub also provides a REST API for administration of the Hub and users.
The documentation on `Using JupyterHub's REST API <../reference/rest.html>`_ provides
information on:
- what you can do with the API
- creating an API token
- adding API tokens to the config files
- making an API request programmatically using the requests library
- learning more about JupyterHub's API
The same JupyterHub API spec, as found here, is available in an interactive form
`here (on swagger's petstore) <http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyterhub/jupyterhub/master/docs/rest-api.yml#!/default>`__.
The `OpenAPI Initiative`_ (fka Swagger™) is a project used to describe
and document RESTful APIs.
JupyterHub API Reference:
.. toctree::
app
auth
spawner
proxy
user
service
services.auth
.. _OpenAPI Initiative: https://www.openapis.org/

23
docs/source/api/proxy.rst Normal file
View File

@@ -0,0 +1,23 @@
=======
Proxies
=======
Module: :mod:`jupyterhub.proxy`
===============================
.. automodule:: jupyterhub.proxy
.. currentmodule:: jupyterhub.proxy
:class:`Proxy`
--------------
.. autoconfigurable:: Proxy
:members:
:class:`ConfigurableHTTPProxy`
------------------------------
.. autoconfigurable:: ConfigurableHTTPProxy
:members: debug, auth_token, check_running_interval, api_url, command

View File

@@ -0,0 +1,17 @@
========
Services
========
Module: :mod:`jupyterhub.services.service`
==========================================
.. automodule:: jupyterhub.services.service
.. currentmodule:: jupyterhub.services.service
:class:`Service`
----------------
.. autoconfigurable:: Service
:members: name, admin, url, api_token, managed, kind, command, cwd, environment, user, oauth_client_id, server, prefix, proxy_spec

View File

@@ -0,0 +1,41 @@
=======================
Services Authentication
=======================
Module: :mod:`jupyterhub.services.auth`
=======================================
.. automodule:: jupyterhub.services.auth
.. currentmodule:: jupyterhub.services.auth
:class:`HubAuth`
----------------
.. autoconfigurable:: HubAuth
:members:
:class:`HubOAuth`
-----------------
.. autoconfigurable:: HubOAuth
:members:
:class:`HubAuthenticated`
-------------------------
.. autoclass:: HubAuthenticated
:members:
:class:`HubOAuthenticated`
--------------------------
.. autoclass:: HubOAuthenticated
:class:`HubOAuthCallbackHandler`
--------------------------------
.. autoclass:: HubOAuthCallbackHandler

View File

@@ -0,0 +1,22 @@
========
Spawners
========
Module: :mod:`jupyterhub.spawner`
=================================
.. automodule:: jupyterhub.spawner
.. currentmodule:: jupyterhub.spawner
:class:`Spawner`
----------------
.. autoconfigurable:: Spawner
:members: options_from_form, poll, start, stop, get_args, get_env, get_state, template_namespace, format_string
:class:`LocalProcessSpawner`
----------------------------
.. autoconfigurable:: LocalProcessSpawner

37
docs/source/api/user.rst Normal file
View File

@@ -0,0 +1,37 @@
=====
Users
=====
Module: :mod:`jupyterhub.user`
==============================
.. automodule:: jupyterhub.user
.. currentmodule:: jupyterhub.user
:class:`UserDict`
-----------------
.. autoclass:: UserDict
:members:
:class:`User`
-------------
.. autoclass:: User
:members: escaped_name
.. attribute:: name
The user's name
.. attribute:: server
The user's Server data object if running, None otherwise.
Has ``ip``, ``port`` attributes.
.. attribute:: spawner
The user's :class:`~.Spawner` instance.

249
docs/source/changelog.md Normal file
View File

@@ -0,0 +1,249 @@
# Changelog
For detailed changes from the prior release, click on the version number, and
its link will bring up a GitHub listing of changes. Use `git log` on the
command line for details.
## [Unreleased]
## [0.8.0] 2017-10-03
JupyterHub 0.8 is a big release!
Perhaps the biggest change is the use of OAuth to negotiate authentication
between the Hub and single-user services.
Due to this change, it is important that the single-user server
and Hub are both running the same version of JupyterHub.
If you are using containers (e.g. via DockerSpawner or KubeSpawner),
this means upgrading jupyterhub in your user images at the same time as the Hub.
In most cases, a
pip install jupyterhub==version
in your Dockerfile is sufficient.
#### Added
- JupyterHub now defined a `Proxy` API for custom
proxy implementations other than the default.
The defaults are unchanged,
but configuration of the proxy is now done on the `ConfigurableHTTPProxy` class instead of the top-level JupyterHub.
TODO: docs for writing a custom proxy.
- Single-user servers and services
(anything that uses HubAuth)
can now accept token-authenticated requests via the Authentication header.
- Authenticators can now store state in the Hub's database.
To do so, the `authenticate` method should return a dict of the form
```python
{
'username': 'name'
'state': {}
}
```
This data will be encrypted and requires `JUPYTERHUB_CRYPT_KEY` environment variable to be set
and the `Authenticator.enable_auth_state` flag to be True.
If these are not set, auth_state returned by the Authenticator will not be stored.
- There is preliminary support for multiple (named) servers per user in the REST API.
Named servers can be created via API requests, but there is currently no UI for managing them.
- Add `LocalProcessSpawner.popen_kwargs` and `LocalProcessSpawner.shell_cmd`
for customizing how user server processes are launched.
- Add `Authenticator.auto_login` flag for skipping the "Login with..." page explicitly.
- Add `JupyterHub.hub_connect_ip` configuration
for the ip that should be used when connecting to the Hub.
This is promoting (and deprecating) `DockerSpawner.hub_ip_connect`
for use by all Spawners.
- Add `Spawner.pre_spawn_hook(spawner)` hook for customizing
pre-spawn events.
- Add `JupyterHub.active_server_limit` and `JupyterHub.concurrent_spawn_limit`
for limiting the total number of running user servers and the number of pending spawns, respectively.
#### Changed
- more arguments to spawners are now passed via environment variables (`.get_env()`)
rather than CLI arguments (`.get_args()`)
- internally generated tokens no longer get extra hash rounds,
significantly speeding up authentication.
The hash rounds were deemed unnecessary because the tokens were already
generated with high entropy.
- `JUPYTERHUB_API_TOKEN` env is available at all times,
rather than being removed during single-user start.
The token is now accessible to kernel processes,
enabling user kernels to make authenticated API requests to Hub-authenticated services.
- Cookie secrets should be 32B hex instead of large base64 secrets.
- pycurl is used by default, if available.
#### Fixed
So many things fixed!
- Collisions are checked when users are renamed
- Fix bug where OAuth authenticators could not logout users
due to being redirected right back through the login process.
- If there are errors loading your config files,
JupyterHub will refuse to start with an informative error.
Previously, the bad config would be ignored and JupyterHub would launch with default configuration.
- Raise 403 error on unauthorized user rather than redirect to login,
which could cause redirect loop.
- Set `httponly` on cookies because it's prudent.
- Improve support for MySQL as the database backend
- Many race conditions and performance problems under heavy load have been fixed.
- Fix alembic tagging of database schema versions.
#### Removed
- End support for Python 3.3
## 0.7
### [0.7.2] - 2017-01-09
#### Added
- Support service environment variables and defaults in `jupyterhub-singleuser`
for easier deployment of notebook servers as a Service.
- Add `--group` parameter for deploying `jupyterhub-singleuser` as a Service with group authentication.
- Include URL parameters when redirecting through `/user-redirect/`
### Fixed
- Fix group authentication for HubAuthenticated services
### [0.7.1] - 2017-01-02
#### Added
- `Spawner.will_resume` for signaling that a single-user server is paused instead of stopped.
This is needed for cases like `DockerSpawner.remove_containers = False`,
where the first API token is re-used for subsequent spawns.
- Warning on startup about single-character usernames,
caused by common `set('string')` typo in config.
#### Fixed
- Removed spurious warning about empty `next_url`, which is AOK.
### [0.7.0] - 2016-12-2
#### Added
- Implement Services API [\#705](https://github.com/jupyterhub/jupyterhub/pull/705)
- Add `/api/` and `/api/info` endpoints [\#675](https://github.com/jupyterhub/jupyterhub/pull/675)
- Add documentation for JupyterLab, pySpark configuration, troubleshooting,
and more.
- Add logging of error if adding users already in database. [\#689](https://github.com/jupyterhub/jupyterhub/pull/689)
- Add HubAuth class for authenticating with JupyterHub. This class can
be used by any application, even outside tornado.
- Add user groups.
- Add `/hub/user-redirect/...` URL for redirecting users to a file on their own server.
#### Changed
- Always install with setuptools but not eggs (effectively require
`pip install .`) [\#722](https://github.com/jupyterhub/jupyterhub/pull/722)
- Updated formatting of changelog. [\#711](https://github.com/jupyterhub/jupyterhub/pull/711)
- Single-user server is provided by JupyterHub package, so single-user servers depend on JupyterHub now.
#### Fixed
- Fix docker repository location [\#719](https://github.com/jupyterhub/jupyterhub/pull/719)
- Fix swagger spec conformance and timestamp type in API spec
- Various redirect-loop-causing bugs have been fixed.
#### Removed
- Deprecate `--no-ssl` command line option. It has no meaning and warns if
used. [\#789](https://github.com/jupyterhub/jupyterhub/pull/789)
- Deprecate `%U` username substitution in favor of `{username}`. [\#748](https://github.com/jupyterhub/jupyterhub/pull/748)
- Removed deprecated SwarmSpawner link. [\#699](https://github.com/jupyterhub/jupyterhub/pull/699)
## 0.6
### [0.6.1] - 2016-05-04
Bugfixes on 0.6:
- statsd is an optional dependency, only needed if in use
- Notice more quickly when servers have crashed
- Better error pages for proxy errors
- Add Stop All button to admin panel for stopping all servers at once
### [0.6.0] - 2016-04-25
- JupyterHub has moved to a new `jupyterhub` namespace on GitHub and Docker. What was `juptyer/jupyterhub` is now `jupyterhub/jupyterhub`, etc.
- `jupyterhub/jupyterhub` image on DockerHub no longer loads the jupyterhub_config.py in an ONBUILD step. A new `jupyterhub/jupyterhub-onbuild` image does this
- Add statsd support, via `c.JupyterHub.statsd_{host,port,prefix}`
- Update to traitlets 4.1 `@default`, `@observe` APIs for traits
- Allow disabling PAM sessions via `c.PAMAuthenticator.open_sessions = False`. This may be needed on SELinux-enabled systems, where our PAM session logic often does not work properly
- Add `Spawner.environment` configurable, for defining extra environment variables to load for single-user servers
- JupyterHub API tokens can be pregenerated and loaded via `JupyterHub.api_tokens`, a dict of `token: username`.
- JupyterHub API tokens can be requested via the REST API, with a POST request to `/api/authorizations/token`.
This can only be used if the Authenticator has a username and password.
- Various fixes for user URLs and redirects
## [0.5] - 2016-03-07
- Single-user server must be run with Jupyter Notebook ≥ 4.0
- Require `--no-ssl` confirmation to allow the Hub to be run without SSL (e.g. behind SSL termination in nginx)
- Add lengths to text fields for MySQL support
- Add `Spawner.disable_user_config` for preventing user-owned configuration from modifying single-user servers.
- Fixes for MySQL support.
- Add ability to run each user's server on its own subdomain. Requires wildcard DNS and wildcard SSL to be feasible. Enable subdomains by setting `JupyterHub.subdomain_host = 'https://jupyterhub.domain.tld[:port]'`.
- Use `127.0.0.1` for local communication instead of `localhost`, avoiding issues with DNS on some systems.
- Fix race that could add users to proxy prematurely if spawning is slow.
## 0.4
### [0.4.1] - 2016-02-03
Fix removal of `/login` page in 0.4.0, breaking some OAuth providers.
### [0.4.0] - 2016-02-01
- Add `Spawner.user_options_form` for specifying an HTML form to present to users,
allowing users to influence the spawning of their own servers.
- Add `Authenticator.pre_spawn_start` and `Authenticator.post_spawn_stop` hooks,
so that Authenticators can do setup or teardown (e.g. passing credentials to Spawner,
mounting data sources, etc.).
These methods are typically used with custom Authenticator+Spawner pairs.
- 0.4 will be the last JupyterHub release where single-user servers running IPython 3 is supported instead of Notebook ≥ 4.0.
## [0.3] - 2015-11-04
- No longer make the user starting the Hub an admin
- start PAM sessions on login
- hooks for Authenticators to fire before spawners start and after they stop,
allowing deeper interaction between Spawner/Authenticator pairs.
- login redirect fixes
## [0.2] - 2015-07-12
- Based on standalone traitlets instead of IPython.utils.traitlets
- multiple users in admin panel
- Fixes for usernames that require escaping
## 0.1 - 2015-03-07
First preview release
[Unreleased]: https://github.com/jupyterhub/jupyterhub/compare/0.8.0...HEAD
[0.8.0]: https://github.com/jupyterhub/jupyterhub/compare/0.7.2...0.8.0
[0.7.2]: https://github.com/jupyterhub/jupyterhub/compare/0.7.1...0.7.2
[0.7.1]: https://github.com/jupyterhub/jupyterhub/compare/0.7.0...0.7.1
[0.7.0]: https://github.com/jupyterhub/jupyterhub/compare/0.6.1...0.7.0
[0.6.1]: https://github.com/jupyterhub/jupyterhub/compare/0.6.0...0.6.1
[0.6.0]: https://github.com/jupyterhub/jupyterhub/compare/0.5.0...0.6.0
[0.5]: https://github.com/jupyterhub/jupyterhub/compare/0.4.1...0.5.0
[0.4.1]: https://github.com/jupyterhub/jupyterhub/compare/0.4.0...0.4.1
[0.4.0]: https://github.com/jupyterhub/jupyterhub/compare/0.3.0...0.4.0
[0.3]: https://github.com/jupyterhub/jupyterhub/compare/0.2.0...0.3.0
[0.2]: https://github.com/jupyterhub/jupyterhub/compare/0.1.0...0.2.0

191
docs/source/conf.py Normal file
View File

@@ -0,0 +1,191 @@
# -*- coding: utf-8 -*-
#
import sys
import os
import shlex
# For conversion from markdown to html
import recommonmark.parser
# Set paths
sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# Minimal Sphinx version
needs_sphinx = '1.4'
# Sphinx extension modules
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.napoleon',
'autodoc_traits',
'jupyter_alabaster_theme',
]
templates_path = ['_templates']
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'JupyterHub'
copyright = u'2016, Project Jupyter team'
author = u'Project Jupyter team'
# Autopopulate version
from os.path import dirname
docs = dirname(dirname(__file__))
root = dirname(docs)
sys.path.insert(0, root)
sys.path.insert(0, os.path.join(docs, 'sphinxext'))
import jupyterhub
# The short X.Y version.
version = '%i.%i' % jupyterhub.version_info[:2]
# The full version, including alpha/beta/rc tags.
release = jupyterhub.__version__
language = None
exclude_patterns = []
pygments_style = 'sphinx'
todo_include_todos = False
# Set the default role so we can use `foo` instead of ``foo``
default_role = 'literal'
# -- Source -------------------------------------------------------------
source_parsers = {
'.md': 'recommonmark.parser.CommonMarkParser',
}
source_suffix = ['.rst', '.md']
#source_encoding = 'utf-8-sig'
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages.
html_theme = 'jupyter_alabaster_theme'
#html_theme_options = {}
#html_theme_path = []
#html_title = None
#html_short_title = None
#html_logo = None
#html_favicon = None
# Paths that contain custom static files (such as style sheets)
html_static_path = ['_static']
#html_extra_path = []
#html_last_updated_fmt = '%b %d, %Y'
#html_use_smartypants = True
#html_sidebars = {}
#html_additional_pages = {}
#html_domain_indices = True
#html_use_index = True
#html_split_index = False
#html_show_sourcelink = True
#html_show_sphinx = True
#html_show_copyright = True
#html_use_opensearch = ''
#html_file_suffix = None
#html_search_language = 'en'
#html_search_options = {'type': 'default'}
#html_search_scorer = 'scorer.js'
htmlhelp_basename = 'JupyterHubdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
#'papersize': 'letterpaper',
#'pointsize': '10pt',
#'preamble': '',
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'JupyterHub.tex', u'JupyterHub Documentation',
u'Project Jupyter team', 'manual'),
]
#latex_logo = None
#latex_use_parts = False
#latex_show_pagerefs = False
#latex_show_urls = False
#latex_appendices = []
#latex_domain_indices = True
# -- manual page output -------------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'jupyterhub', u'JupyterHub Documentation',
[author], 1)
]
#man_show_urls = False
# -- Texinfo output -----------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'JupyterHub', u'JupyterHub Documentation',
author, 'JupyterHub', 'One line description of project.',
'Miscellaneous'),
]
#texinfo_appendices = []
#texinfo_domain_indices = True
#texinfo_show_urls = 'footnote'
#texinfo_no_detailmenu = False
# -- Epub output --------------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
epub_author = author
epub_publisher = author
epub_copyright = copyright
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# -- Intersphinx ----------------------------------------------------------
intersphinx_mapping = {'https://docs.python.org/3/': None}
# -- Read The Docs --------------------------------------------------------
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd:
import jupyter_alabaster_theme
html_theme = 'jupyter_alabaster_theme'
html_theme_path = [jupyter_alabaster_theme.get_path()]
else:
# readthedocs.org uses their theme by default, so no need to specify it
# build rest-api, since RTD doesn't run make
from subprocess import check_call as sh
sh(['make', 'rest-api'], cwd=docs)
# -- Spell checking -------------------------------------------------------
try:
import sphinxcontrib.spelling
except ImportError:
pass
else:
extensions.append("sphinxcontrib.spelling")
spelling_word_list_filename='spelling_wordlist.txt'

View File

@@ -0,0 +1,78 @@
# Contributors
Project Jupyter thanks the following people for their help and
contribution on JupyterHub:
- Analect
- anderbubble
- apetresc
- barrachri
- betatim
- Carreau
- charnpreetsingh
- ckald
- CRegenschein
- cwaldbieser
- danielballen
- danoventa
- daradib
- datapolitan
- dblockow-d2dcrc
- DeepHorizons
- dhirschfeld
- dietmarw
- dmartzol
- DominicFollettSmith
- dsblank
- ellisonbg
- evanlinde
- Fokko
- fperez
- iamed18
- JamiesHQ
- jbweston
- jdavidheiser
- jencabral
- jhamrick
- josephtate
- kinuax
- KrishnaPG
- kroq-gar78
- ksolan
- mbmilligan
- mgeplf
- minrk
- mistercrunch
- Mistobaan
- mwmarkland
- nthiery
- ObiWahn
- ozancaglayan
- parente
- PeterDaveHello
- peterruppel
- pjamason
- prasadkatti
- rafael-ladislau
- rgbkrk
- robnagler
- ryanlovett
- Scrypy
- shreddd
- spoorthyv
- ssanderson
- takluyver
- temogen
- ThomasMChen
- TimShawver
- Todd-Z-Li
- toobaz
- tsaeger
- tschaume
- vilhelmen
- whitead
- willingc
- YannBrrd
- yuvipanda
- zoltan-fedor
- zonca

View File

@@ -0,0 +1,169 @@
# A Gallery of JupyterHub Deployments
**A JupyterHub Community Resource**
We've compiled this list of JupyterHub deployments to help the community
see the breadth and growth of JupyterHub's use in education, research, and
high performance computing.
Please submit pull requests to update information or to add new institutions or uses.
## Academic Institutions, Research Labs, and Supercomputer Centers
### University of California Berkeley
- [BIDS - Berkeley Institute for Data Science](https://bids.berkeley.edu/)
- [Teaching with Jupyter notebooks and JupyterHub](https://bids.berkeley.edu/resources/videos/teaching-ipythonjupyter-notebooks-and-jupyterhub)
- [Data 8](http://data8.org/)
- [GitHub organization](https://github.com/data-8)
- [NERSC](http://www.nersc.gov/)
- [Press release on Jupyter and Cori](http://www.nersc.gov/news-publications/nersc-news/nersc-center-news/2016/jupyter-notebooks-will-open-up-new-possibilities-on-nerscs-cori-supercomputer/)
- [Moving and sharing data](https://www.nersc.gov/assets/Uploads/03-MovingAndSharingData-Cholia.pdf)
- [Research IT](http://research-it.berkeley.edu)
- [JupyterHub server supports campus research computation](http://research-it.berkeley.edu/blog/17/01/24/free-fully-loaded-jupyterhub-server-supports-campus-research-computation)
### University of California Davis
- [Spinning up multiple Jupyter Notebooks on AWS for a tutorial](https://github.com/mblmicdiv/course2017/blob/master/exercises/sourmash-setup.md)
Although not technically a JupyterHub deployment, this tutorial setup
may be helpful to others in the Jupyter community.
Thank you C. Titus Brown for sharing this with the Software Carpentry
mailing list.
```
* I started a big Amazon machine;
* I installed Docker and built a custom image containing my software of
interest;
* I ran multiple containers, one connected to port 8000, one on 8001,
etc. and gave each student a different port;
* students could connect in and use the Terminal program in Jupyter to
execute commands, and could upload/download files via the Jupyter
console interface;
* in theory I could have used notebooks too, but for this I didnt have
need.
I am aware that JupyterHub can probably do all of this including manage
the containers, but Im still a bit shy of diving into that; this was
fairly straightforward, gave me disposable containers that were isolated
for each individual student, and worked almost flawlessly. Should be
easy to do with RStudio too.
```
### Cal Poly San Luis Obispo
- [jupyterhub-deploy-teaching](https://github.com/jupyterhub/jupyterhub-deploy-teaching) based on work by Brian Granger for Cal Poly's Data Science 301 Course
### Clemson University
- Advanced Computing
- [Palmetto cluster and JupyterHub](http://citi.sites.clemson.edu/2016/08/18/JupyterHub-for-Palmetto-Cluster.html)
### University of Colorado Boulder
- (CU Research Computing) CURC
- [JupyterHub User Guide](https://www.rc.colorado.edu/support/user-guide/jupyterhub.html)
- Slurm job dispatched on Crestone compute cluster
- log troubleshooting
- Profiles in IPython Clusters tab
- [Parallel Processing with JupyterHub tutorial](https://www.rc.colorado.edu/support/examples-and-tutorials/parallel-processing-with-jupyterhub.html)
- [Parallel Programming with JupyterHub document](https://www.rc.colorado.edu/book/export/html/833)
- Earth Lab at CU
- [Tutorial on Parallel R on JupyterHub](https://earthdatascience.org/tutorials/parallel-r-on-jupyterhub/)
### HTCondor
- [HTCondor Python Bindings Tutorial from HTCondor Week 2017 includes information on their JupyterHub tutorials](https://research.cs.wisc.edu/htcondor/HTCondorWeek2017/presentations/TueBockelman_Python.pdf)
### University of Illinois
- https://datascience.business.illinois.edu
### MIT and Lincoln Labs
### Michigan State University
- [Setting up JupyterHub](https://mediaspace.msu.edu/media/Setting+Up+Your+JupyterHub+Password/1_hgv13aag/11980471)
### University of Minnesota
- [JupyterHub Inside HPC](https://insidehpc.com/tag/jupyterhub/)
### University of Missouri
- https://dsa.missouri.edu/faq/
### University of Rochester CIRC
- [JupyterHub Userguide](https://info.circ.rochester.edu/Web_Applications/JupyterHub.html) - Slurm, beehive
### University of California San Diego
- San Diego Supercomputer Center - Andrea Zonca
- [Deploy JupyterHub on a Supercomputer with SSH](https://zonca.github.io/2017/05/jupyterhub-hpc-batchspawner-ssh.html)
- [Run Jupyterhub on a Supercomputer](https://zonca.github.io/2015/04/jupyterhub-hpc.html)
- [Deploy JupyterHub on a VM for a Workshop](https://zonca.github.io/2016/04/jupyterhub-sdsc-cloud.html)
- [Customize your Python environment in Jupyterhub](https://zonca.github.io/2017/02/customize-python-environment-jupyterhub.html)
- [Jupyterhub deployment on multiple nodes with Docker Swarm](https://zonca.github.io/2016/05/jupyterhub-docker-swarm.html)
- [Sample deployment of Jupyterhub in HPC on SDSC Comet](https://zonca.github.io/2017/02/sample-deployment-jupyterhub-hpc.html)
- Educational Technology Services - Paul Jamason
- [jupyterhub.ucsd.edu](https://jupyterhub.ucsd.edu)
### TACC University of Texas
### Texas A&M
- Kristen Thyng - Oceanography
- [Teaching with JupyterHub and nbgrader](http://kristenthyng.com/blog/2016/09/07/jupyterhub+nbgrader/)
## Service Providers
### AWS
- [running-jupyter-notebook-and-jupyterhub-on-amazon-emr](https://aws.amazon.com/blogs/big-data/running-jupyter-notebook-and-jupyterhub-on-amazon-emr/)
### Google Cloud Platform
- [Using Tensorflow and JupyterHub in Classrooms](https://cloud.google.com/solutions/using-tensorflow-jupyterhub-classrooms)
- [using-tensorflow-and-jupyterhub blog post](https://opensource.googleblog.com/2016/10/using-tensorflow-and-jupyterhub.html)
### Everware
[Everware](https://github.com/everware) Reproducible and reusable science powered by jupyterhub and docker. Like nbviewer, but executable. CERN, Geneva [website](http://everware.xyz/)
### Microsoft Azure
- https://docs.microsoft.com/en-us/azure/machine-learning/machine-learning-data-science-linux-dsvm-intro
### Rackspace Carina
- https://getcarina.com/blog/learning-how-to-whale/
- http://carolynvanslyck.com/talk/carina/jupyterhub/#/
### Red Hat
## Miscellaneous
- https://medium.com/@ybarraud/setting-up-jupyterhub-with-sudospawner-and-anaconda-844628c0dbee#.rm3yt87e1
- https://groups.google.com/forum/#!topic/jupyter/nkPSEeMr8c0 Mailing list UT deployment
- JupyterHub setup on Centos https://gist.github.com/johnrc/604971f7d41ebf12370bf5729bf3e0a4
- Deploy JupyterHub to Docker Swarm https://jupyterhub.surge.sh/#/welcome
- http://www.laketide.com/building-your-lab-part-3/
- http://estrellita.hatenablog.com/entry/2015/07/31/083202
- http://www.walkingrandomly.com/?p=5734
- https://wrdrd.com/docs/consulting/education-technology
- https://bitbucket.org/jackhale/fenics-jupyter
- [LinuxCluster blog](https://linuxcluster.wordpress.com/category/application/jupyterhub/)
- [Network Technology](https://arnesund.com/tag/jupyterhub/) [Spark Cluster on OpenStack with Multi-User Jupyter Notebook](https://arnesund.com/2015/09/21/spark-cluster-on-openstack-with-multi-user-jupyter-notebook/)

View File

@@ -0,0 +1,99 @@
# Authentication and User Basics
The default Authenticator uses [PAM][] to authenticate system users with
their username and password. With the default Authenticator, any user
with an account and password on the system will be allowed to login.
## Create a whitelist of users
You can restrict which users are allowed to login with a whitelist,
`Authenticator.whitelist`:
```python
c.Authenticator.whitelist = {'mal', 'zoe', 'inara', 'kaylee'}
```
Users in the whitelist are added to the Hub database when the Hub is
started.
## Configure admins (`admin_users`)
Admin users of JupyterHub, `admin_users`, can add and remove users from
the user `whitelist`. `admin_users` can take actions on other users'
behalf, such as stopping and restarting their servers.
A set of initial admin users, `admin_users` can configured be as follows:
```python
c.Authenticator.admin_users = {'mal', 'zoe'}
```
Users in the admin list are automatically added to the user `whitelist`,
if they are not already present.
## Give admin access to other users' notebook servers (`admin_access`)
Since the default `JupyterHub.admin_access` setting is False, the admins
do not have permission to log in to the single user notebook servers
owned by *other users*. If `JupyterHub.admin_access` is set to True,
then admins have permission to log in *as other users* on their
respective machines, for debugging. **As a courtesy, you should make
sure your users know if admin_access is enabled.**
## Add or remove users from the Hub
Users can be added to and removed from the Hub via either the admin
panel or the REST API. When a user is **added**, the user will be
automatically added to the whitelist and database. Restarting the Hub
will not require manually updating the whitelist in your config file,
as the users will be loaded from the database.
After starting the Hub once, it is not sufficient to **remove** a user
from the whitelist in your config file. You must also remove the user
from the Hub's database, either by deleting the user from JupyterHub's
admin page, or you can clear the `jupyterhub.sqlite` database and start
fresh.
## Use LocalAuthenticator to create system users
The `LocalAuthenticator` is a special kind of authenticator that has
the ability to manage users on the local system. When you try to add a
new user to the Hub, a `LocalAuthenticator` will check if the user
already exists. If you set the configuration value, `create_system_users`,
to `True` in the configuration file, the `LocalAuthenticator` has
the privileges to add users to the system. The setting in the config
file is:
```python
c.LocalAuthenticator.create_system_users = True
```
Adding a user to the Hub that doesn't already exist on the system will
result in the Hub creating that user via the system `adduser` command
line tool. This option is typically used on hosted deployments of
JupyterHub, to avoid the need to manually create all your users before
launching the service. This approach is not recommended when running
JupyterHub in situations where JupyterHub users map directly onto the
system's UNIX users.
## Use OAuthenticator to support OAuth with popular service providers
JupyterHub's [OAuthenticator][] currently supports the following
popular services:
- Auth0
- Bitbucket
- CILogon
- GitHub
- GitLab
- Globus
- Google
- MediaWiki
- Okpy
- OpenShift
A generic implementation, which you can use for OAuth authentication
with any provider, is also available.
[PAM]: https://en.wikipedia.org/wiki/Pluggable_authentication_module
[OAuthenticator]: https://github.com/jupyterhub/oauthenticator

View File

@@ -0,0 +1,87 @@
# Configuration Basics
The section contains basic information about configuring settings for a JupyterHub
deployment. The [Technical Reference](../reference/index.html)
documentation provides additional details.
This section will help you learn how to:
- generate a default configuration file, `jupyterhub_config.py`
- start with a specific configuration file
- configure JupyterHub using command line options
- find information and examples for some common deployments
## Generate a default config file
On startup, JupyterHub will look by default for a configuration file,
`jupyterhub_config.py`, in the current working directory.
To generate a default config file, `jupyterhub_config.py`:
```bash
jupyterhub --generate-config
```
This default `jupyterhub_config.py` file contains comments and guidance for all
configuration variables and their default values. We recommend storing
configuration files in the standard UNIX filesystem location, i.e.
`/etc/jupyterhub`.
## Start with a specific config file
You can load a specific config file and start JupyterHub using:
```bash
jupyterhub -f /path/to/jupyterhub_config.py
```
If you have stored your configuration file in the recommended UNIX filesystem
location, `/etc/jupyterhub`, the following command will start JupyterHub using
the configuration file:
```bash
jupyterhub -f /etc/jupyterhub/jupyterhub_config.py
```
The IPython documentation provides additional information on the
[config system](http://ipython.readthedocs.io/en/stable/development/config.html)
that Jupyter uses.
## Configure using command line options
To display all command line options that are available for configuration:
```bash
jupyterhub --help-all
```
Configuration using the command line options is done when launching JupyterHub.
For example, to start JupyterHub on ``10.0.1.2:443`` with https, you
would enter:
```bash
jupyterhub --ip 10.0.1.2 --port 443 --ssl-key my_ssl.key --ssl-cert my_ssl.cert
```
All configurable options may technically be set on the command-line,
though some are inconvenient to type. To set a particular configuration
parameter, `c.Class.trait`, you would use the command line option,
`--Class.trait`, when starting JupyterHub. For example, to configure the
`c.Spawner.notebook_dir` trait from the command-line, use the
`--Spawner.notebook_dir` option:
```bash
jupyterhub --Spawner.notebook_dir='~/assignments'
```
## Configure for various deployment environments
The default authentication and process spawning mechanisms can be replaced, and
specific [authenticators](./authenticators-users-basics.html) and
[spawners](./spawners-basics.html) can be set in the configuration file.
This enables JupyterHub to be used with a variety of authentication methods or
process control and deployment environments. [Some examples](../reference/config-examples.html),
meant as illustration, are:
- Using GitHub OAuth instead of PAM with [OAuthenticator](https://github.com/jupyterhub/oauthenticator)
- Spawning single-user servers with Docker, using the [DockerSpawner](https://github.com/jupyterhub/dockerspawner)

View File

@@ -0,0 +1,12 @@
Getting Started
===============
.. toctree::
:maxdepth: 2
config-basics
networking-basics
security-basics
authenticators-users-basics
spawners-basics
services-basics

View File

@@ -0,0 +1,88 @@
# Networking basics
This section will help you with basic proxy and network configuration to:
- set the proxy's IP address and port
- set the proxy's REST API URL
- configure the Hub if the Proxy or Spawners are remote or isolated
- set the `hub_connect_ip` which services will use to communicate with the hub
## Set the Proxy's IP address and port
The Proxy's main IP address setting determines where JupyterHub is available to users.
By default, JupyterHub is configured to be available on all network interfaces
(`''`) on port 8000. *Note*: Use of `'*'` is discouraged for IP configuration;
instead, use of `'0.0.0.0'` is preferred.
Changing the Proxy's main IP address and port can be done with the following
JupyterHub **command line options**:
```bash
jupyterhub --ip=192.168.1.2 --port=443
```
Or by placing the following lines in a **configuration file**,
`jupyterhub_config.py`:
```python
c.JupyterHub.ip = '192.168.1.2'
c.JupyterHub.port = 443
```
Port 443 is used in the examples since 443 is the default port for SSL/HTTPS.
Configuring only the main IP and port of JupyterHub should be sufficient for
most deployments of JupyterHub. However, more customized scenarios may need
additional networking details to be configured.
## Set the Proxy's REST API communication URL (optional)
By default, this REST API listens on port 8081 of `localhost` only.
The Hub service talks to the proxy via a REST API on a secondary port. The
API URL can be configured separately and override the default settings.
### Set api_url
The URL to access the API, `c.configurableHTTPProxy.api_url`, is configurable.
An example entry to set the proxy's API URL in `jupyterhub_config.py` is:
```python
c.ConfigurableHTTPProxy.api_url = 'http://10.0.1.4:5432'
```
### proxy_api_ip and proxy_api_port (Deprecated in 0.8)
If running the Proxy separate from the Hub, configure the REST API communication
IP address and port by adding this to the `jupyterhub_config.py` file:
```python
# ideally a private network address
c.JupyterHub.proxy_api_ip = '10.0.1.4'
c.JupyterHub.proxy_api_port = 5432
```
We recommend using the proxy's `api_url` setting instead of the deprecated
settings, `proxy_api_ip` and `proxy_api_port`.
## Configure the Hub if the Proxy or Spawners are remote or isolated
The Hub service listens only on `localhost` (port 8081) by default.
The Hub needs to be accessible from both the proxy and all Spawners.
When spawning local servers, an IP address setting of `localhost` is fine.
If *either* the Proxy *or* (more likely) the Spawners will be remote or
isolated in containers, the Hub must listen on an IP that is accessible.
```python
c.JupyterHub.hub_ip = '10.0.1.4'
c.JupyterHub.hub_port = 54321
```
**Added in 0.8:** The `c.JupyterHub.hub_connect_ip` setting is the ip address or
hostname that other services should use to connect to the Hub. A common
configuration for, e.g. docker, is:
```python
c.JupyterHub.hub_ip = '0.0.0.0' # listen on all interfaces
c.JupyterHub.hub_connect_ip = '10.0.1.4' # ip as seen on the docker network. Can also be a hostname.
```

View File

@@ -0,0 +1,181 @@
Security settings
=================
.. important::
You should not run JupyterHub without SSL encryption on a public network.
Security is the most important aspect of configuring Jupyter. Three
configuration settings are the main aspects of security configuration:
1. :ref:`SSL encryption <ssl-encryption>` (to enable HTTPS)
2. :ref:`Cookie secret <cookie-secret>` (a key for encrypting browser cookies)
3. Proxy :ref:`authentication token <authentication-token>` (used for the Hub and
other services to authenticate to the Proxy)
The Hub hashes all secrets (e.g., auth tokens) before storing them in its
database. A loss of control over read-access to the database should have
minimal impact on your deployment; if your database has been compromised, it
is still a good idea to revoke existing tokens.
.. _ssl-encryption:
Enabling SSL encryption
-----------------------
Since JupyterHub includes authentication and allows arbitrary code execution,
you should not run it without SSL (HTTPS).
Using an SSL certificate
~~~~~~~~~~~~~~~~~~~~~~~~
This will require you to obtain an official, trusted SSL certificate or create a
self-signed certificate. Once you have obtained and installed a key and
certificate you need to specify their locations in the ``jupyterhub_config.py``
configuration file as follows:
.. code-block:: python
c.JupyterHub.ssl_key = '/path/to/my.key'
c.JupyterHub.ssl_cert = '/path/to/my.cert'
Some cert files also contain the key, in which case only the cert is needed. It
is important that these files be put in a secure location on your server, where
they are not readable by regular users.
If you are using a **chain certificate**, see also chained certificate for SSL
in the JupyterHub `troubleshooting FAQ <troubleshooting>`_.
Using letsencrypt
~~~~~~~~~~~~~~~~~
It is also possible to use `letsencrypt <https://letsencrypt.org/>`_ to obtain
a free, trusted SSL certificate. If you run letsencrypt using the default
options, the needed configuration is (replace ``mydomain.tld`` by your fully
qualified domain name):
.. code-block:: python
c.JupyterHub.ssl_key = '/etc/letsencrypt/live/{mydomain.tld}/privkey.pem'
c.JupyterHub.ssl_cert = '/etc/letsencrypt/live/{mydomain.tld}/fullchain.pem'
If the fully qualified domain name (FQDN) is ``example.com``, the following
would be the needed configuration:
.. code-block:: python
c.JupyterHub.ssl_key = '/etc/letsencrypt/live/example.com/privkey.pem'
c.JupyterHub.ssl_cert = '/etc/letsencrypt/live/example.com/fullchain.pem'
If SSL termination happens outside of the Hub
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In certain cases, e.g. behind `SSL termination in NGINX <https://www.nginx.com/resources/admin-guide/nginx-ssl-termination/>`_,
allowing no SSL running on the hub may be the desired configuration option.
.. _cookie-secret:
Cookie secret
-------------
The cookie secret is an encryption key, used to encrypt the browser cookies
which are used for authentication. Three common methods are described for
generating and configuring the cookie secret.
Generating and storing as a cookie secret file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The cookie secret should be 32 random bytes, encoded as hex, and is typically
stored in a ``jupyterhub_cookie_secret`` file. An example command to generate the
``jupyterhub_cookie_secret`` file is:
.. code-block:: bash
openssl rand -hex 32 > /srv/jupyterhub/jupyterhub_cookie_secret
In most deployments of JupyterHub, you should point this to a secure location on
the file system, such as ``/srv/jupyterhub/jupyterhub_cookie_secret``.
The location of the ``jupyterhub_cookie_secret`` file can be specified in the
``jupyterhub_config.py`` file as follows:
.. code-block:: python
c.JupyterHub.cookie_secret_file = '/srv/jupyterhub/jupyterhub_cookie_secret'
If the cookie secret file doesn't exist when the Hub starts, a new cookie
secret is generated and stored in the file. The file must not be readable by
``group`` or ``other`` or the server won't start. The recommended permissions
for the cookie secret file are ``600`` (owner-only rw).
Generating and storing as an environment variable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you would like to avoid the need for files, the value can be loaded in the
Hub process from the ``JPY_COOKIE_SECRET`` environment variable, which is a
hex-encoded string. You can set it this way:
.. code-block:: bash
export JPY_COOKIE_SECRET=`openssl rand -hex 32`
For security reasons, this environment variable should only be visible to the
Hub. If you set it dynamically as above, all users will be logged out each time
the Hub starts.
Generating and storing as a binary string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can also set the cookie secret in the configuration file
itself, ``jupyterhub_config.py``, as a binary string:
.. code-block:: python
c.JupyterHub.cookie_secret = bytes.fromhex('64 CHAR HEX STRING')
.. important::
If the cookie secret value changes for the Hub, all single-user notebook
servers must also be restarted.
.. _authentication-token:
Proxy authentication token
--------------------------
The Hub authenticates its requests to the Proxy using a secret token that
the Hub and Proxy agree upon. The value of this string should be a random
string (for example, generated by ``openssl rand -hex 32``).
Generating and storing token in the configuration file
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Or you can set the value in the configuration file, ``jupyterhub_config.py``:
.. code-block:: python
c.JupyterHub.proxy_auth_token = '0bc02bede919e99a26de1e2a7a5aadfaf6228de836ec39a05a6c6942831d8fe5'
Generating and storing as an environment variable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can pass this value of the proxy authentication token to the Hub and Proxy
using the ``CONFIGPROXY_AUTH_TOKEN`` environment variable:
.. code-block:: bash
export CONFIGPROXY_AUTH_TOKEN='openssl rand -hex 32'
This environment variable needs to be visible to the Hub and Proxy.
Default if token is not set
~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you don't set the Proxy authentication token, the Hub will generate a random
key itself, which means that any time you restart the Hub you **must also
restart the Proxy**. If the proxy is a subprocess of the Hub, this should happen
automatically (this is the default configuration).

View File

@@ -0,0 +1,121 @@
# External services
When working with JupyterHub, a **Service** is defined as a process
that interacts with the Hub's REST API. A Service may perform a specific
or action or task. For example, shutting down individuals' single user
notebook servers that have been is a good example of a task that could
be automated by a Service. Let's look at how the [cull_idle_servers][]
script can be used as a Service.
## Real-world example to cull idle servers
JupyterHub has a REST API that can be used by external services. This
document will:
- explain some basic information about API tokens
- clarify that API tokens can be used to authenticate to
single-user servers as of [version 0.8.0](../changelog.html)
- show how the [cull_idle_servers][] script can be:
- used in a Hub-managed service
- run as a standalone script
Both examples for `cull_idle_servers` will communicate tasks to the
Hub via the REST API.
## API Token basics
### Create an API token
To run such an external service, an API token must be created and
provided to the service.
As of [version 0.6.0](../changelog.html), the preferred way of doing
this is to first generate an API token:
```bash
openssl rand -hex 32
```
In [version 0.8.0](../changelog.html), a TOKEN request page for
generating an API token is available from the JupyterHub user interface:
![Request API TOKEN page](../images/token-request.png)
![API TOKEN success page](../images/token-request-success.png)
### Pass environment variable with token to the Hub
In the case of `cull_idle_servers`, it is passed as the environment
variable called `JUPYTERHUB_API_TOKEN`.
### Use API tokens for services and tasks that require external access
While API tokens are often associated with a specific user, API tokens
can be used by services that require external access for activities
that may not correspond to a specific human, e.g. adding users during
setup for a tutorial or workshop. Add a service and its API token to the
JupyterHub configuration file, `jupyterhub_config.py`:
```python
c.JupyterHub.services = [
{'name': 'adding-users', 'api_token': 'super-secret-token'},
]
```
### Restart JupyterHub
Upon restarting JupyterHub, you should see a message like below in the
logs:
```
Adding API token for <username>
```
## Authenticating to single-user servers using API token
In JupyterHub 0.7, there is no mechanism for token authentication to
single-user servers, and only cookies can be used for authentication.
0.8 supports using JupyterHub API tokens to authenticate to single-user
servers.
## Configure `cull-idle` to run as a Hub-Managed Service
In `jupyterhub_config.py`, add the following dictionary for the
`cull-idle` Service to the `c.JupyterHub.services` list:
```python
c.JupyterHub.services = [
{
'name': 'cull-idle',
'admin': True,
'command': 'python cull_idle_servers.py --timeout=3600'.split(),
}
]
```
where:
- `'admin': True` indicates that the Service has 'admin' permissions, and
- `'command'` indicates that the Service will be launched as a
subprocess, managed by the Hub.
## Run `cull-idle` manually as a standalone script
Now you can run your script, i.e. `cull_idle_servers`, by providing it
the API token and it will authenticate through the REST API to
interact with it.
This will run `cull-idle` manually. `cull-idle` can be run as a standalone
script anywhere with access to the Hub, and will periodically check for idle
servers and shut them down via the Hub's REST API. In order to shutdown the
servers, the token given to cull-idle must have admin privileges.
Generate an API token and store it in the `JUPYTERHUB_API_TOKEN` environment
variable. Run `cull_idle_servers.py` manually.
```bash
export JUPYTERHUB_API_TOKEN='token'
python cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
```
[cull_idle_servers]: https://github.com/jupyterhub/jupyterhub/blob/master/examples/cull-idle/cull_idle_servers.py

View File

@@ -0,0 +1,33 @@
# Spawners and single-user notebook servers
Since the single-user server is an instance of `jupyter notebook`, an entire separate
multi-process application, there are many aspect of that server can configure, and a lot of ways
to express that configuration.
At the JupyterHub level, you can set some values on the Spawner. The simplest of these is
`Spawner.notebook_dir`, which lets you set the root directory for a user's server. This root
notebook directory is the highest level directory users will be able to access in the notebook
dashboard. In this example, the root notebook directory is set to `~/notebooks`, where `~` is
expanded to the user's home directory.
```python
c.Spawner.notebook_dir = '~/notebooks'
```
You can also specify extra command-line arguments to the notebook server with:
```python
c.Spawner.args = ['--debug', '--profile=PHYS131']
```
This could be used to set the users default page for the single user server:
```python
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
```
Since the single-user server extends the notebook server application,
it still loads configuration from the `jupyter_notebook_config.py` config file.
Each user may have one of these files in `$HOME/.jupyter/`.
Jupyter also supports loading system-wide config files from `/etc/jupyter/`,
which is the place to put configuration that you want to affect all of your users.

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

120
docs/source/index.rst Normal file
View File

@@ -0,0 +1,120 @@
JupyterHub
==========
`JupyterHub`_, a multi-user **Hub**, spawns, manages, and proxies multiple
instances of the single-user `Jupyter notebook`_ server.
JupyterHub can be used to serve notebooks to a class of students, a corporate
data science group, or a scientific research group.
.. image:: images/jhub-parts.png
:alt: JupyterHub subsystems
:width: 40%
:align: right
Three subsystems make up JupyterHub:
* a multi-user **Hub** (tornado process)
* a **configurable http proxy** (node-http-proxy)
* multiple **single-user Jupyter notebook servers** (Python/IPython/tornado)
JupyterHub performs the following functions:
- The Hub spawns a proxy
- The proxy forwards all requests to the Hub by default
- The Hub handles user login and spawns single-user servers on demand
- The Hub configures the proxy to forward URL prefixes to the single-user
notebook servers
For convenient administration of the Hub, its users, and services,
JupyterHub also provides a `REST API`_.
Contents
--------
**Installation Guide**
* :doc:`installation-guide`
* :doc:`quickstart`
* :doc:`quickstart-docker`
* :doc:`installation-basics`
**Getting Started**
* :doc:`getting-started/index`
* :doc:`getting-started/config-basics`
* :doc:`getting-started/networking-basics`
* :doc:`getting-started/security-basics`
* :doc:`getting-started/authenticators-users-basics`
* :doc:`getting-started/spawners-basics`
* :doc:`getting-started/services-basics`
**Technical Reference**
* :doc:`reference/index`
* :doc:`reference/technical-overview`
* :doc:`reference/websecurity`
* :doc:`reference/authenticators`
* :doc:`reference/spawners`
* :doc:`reference/services`
* :doc:`reference/rest`
* :doc:`reference/upgrading`
* :doc:`reference/config-examples`
**API Reference**
* :doc:`api/index`
**Tutorials**
* :doc:`tutorials/index`
* :doc:`tutorials/upgrade-dot-eight`
* `Zero to JupyterHub with Kubernetes <https://zero-to-jupyterhub.readthedocs.io/en/latest/>`_
**Troubleshooting**
* :doc:`troubleshooting`
**About JupyterHub**
* :doc:`contributor-list`
* :doc:`gallery-jhub-deployments`
**Changelog**
* :doc:`changelog`
Indices and tables
------------------
* :ref:`genindex`
* :ref:`modindex`
Questions? Suggestions?
-----------------------
- `Jupyter mailing list <https://groups.google.com/forum/#!forum/jupyter>`_
- `Jupyter website <https://jupyter.org>`_
.. _contents:
Full Table of Contents
----------------------
.. toctree::
:maxdepth: 2
installation-guide
getting-started/index
reference/index
api/index
tutorials/index
troubleshooting
contributor-list
gallery-jhub-deployments
changelog
.. _JupyterHub: https://github.com/jupyterhub/jupyterhub
.. _Jupyter notebook: https://jupyter-notebook.readthedocs.io/en/latest/
.. _REST API: http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyterhub/jupyterhub/master/docs/rest-api.yml#!/default

View File

@@ -0,0 +1,40 @@
# Installation Basics
## Platform support
JupyterHub is supported on Linux/Unix based systems. To use JupyterHub, you need
a Unix server (typically Linux) running somewhere that is accessible to your
team on the network. The JupyterHub server can be on an internal network at your
organization, or it can run on the public internet (in which case, take care
with the Hub's [security](./security-basics.html)).
JupyterHub officially **does not** support Windows. You may be able to use
JupyterHub on Windows if you use a Spawner and Authenticator that work on
Windows, but the JupyterHub defaults will not. Bugs reported on Windows will not
be accepted, and the test suite will not run on Windows. Small patches that fix
minor Windows compatibility issues (such as basic installation) **may** be accepted,
however. For Windows-based systems, we would recommend running JupyterHub in a
docker container or Linux VM.
[Additional Reference:](http://www.tornadoweb.org/en/stable/#installation)
Tornado's documentation on Windows platform support
## Planning your installation
Prior to beginning installation, it's helpful to consider some of the following:
- deployment system (bare metal, Docker)
- Authentication (PAM, OAuth, etc.)
- Spawner of singleuser notebook servers (Docker, Batch, etc.)
- Services (nbgrader, etc.)
- JupyterHub database (default SQLite; traditional RDBMS such as PostgreSQL,)
MySQL, or other databases supported by [SQLAlchemy](http://www.sqlalchemy.org))
## Folders and File Locations
It is recommended to put all of the files used by JupyterHub into standard
UNIX filesystem locations.
- `/srv/jupyterhub` for all security and runtime files
- `/etc/jupyterhub` for all configuration files
- `/var/log` for log files

View File

@@ -0,0 +1,9 @@
Installation Guide
==================
.. toctree::
:maxdepth: 3
quickstart
quickstart-docker
installation-basics

View File

@@ -0,0 +1,49 @@
Using Docker
============
.. important::
We highly recommend following the `Zero to JupyterHub`_ tutorial for
installing JupyterHub.
Alternate installation using Docker
-----------------------------------
A ready to go `docker image <https://hub.docker.com/r/jupyterhub/jupyterhub/>`_
gives a straightforward deployment of JupyterHub.
.. note::
This ``jupyterhub/jupyterhub`` docker image is only an image for running
the Hub service itself. It does not provide the other Jupyter components,
such as Notebook installation, which are needed by the single-user servers.
To run the single-user servers, which may be on the same system as the Hub or
not, Jupyter Notebook version 4 or greater must be installed.
Starting JupyterHub with docker
-------------------------------
The JupyterHub docker image can be started with the following command::
docker run -d --name jupyterhub jupyterhub/jupyterhub jupyterhub
This command will create a container named ``jupyterhub`` that you can
**stop and resume** with ``docker stop/start``.
The Hub service will be listening on all interfaces at port 8000, which makes
this a good choice for **testing JupyterHub on your desktop or laptop**.
If you want to run docker on a computer that has a public IP then you should
(as in MUST) **secure it with ssl** by adding ssl options to your docker
configuration or using a ssl enabled proxy.
`Mounting volumes <https://docs.docker.com/engine/userguide/containers/dockervolumes/>`_
will allow you to store data outside the docker image (host system) so it will
be persistent, even when you start a new image.
The command ``docker exec -it jupyterhub bash`` will spawn a root shell in your
docker container. You can use the root shell to **create system users in the container**.
These accounts will be used for authentication in JupyterHub's default
configuration.
.. _Zero to JupyterHub: https://zero-to-jupyterhub.readthedocs.io/en/latest/

78
docs/source/quickstart.md Normal file
View File

@@ -0,0 +1,78 @@
# Quickstart
## Prerequisites
Before installing JupyterHub, you will need:
- a Linux/Unix based system
- [Python](https://www.python.org/downloads/) 3.4 or greater. An understanding
of using [`pip`](https://pip.pypa.io/en/stable/) or
[`conda`](https://conda.io/docs/get-started.html) for
installing Python packages is helpful.
- [nodejs/npm](https://www.npmjs.com/). [Install nodejs/npm](https://docs.npmjs.com/getting-started/installing-node),
using your operating system's package manager. For example, install on Linux
Debian/Ubuntu using:
```bash
sudo apt-get install npm nodejs-legacy
```
The `nodejs-legacy` package installs the `node` executable and is currently
required for `npm` to work on Debian/Ubuntu.
- TLS certificate and key for HTTPS communication
- Domain name
Before running the single-user notebook servers (which may be on the same
system as the Hub or not), you will need:
- [Jupyter Notebook](https://jupyter.readthedocs.io/en/latest/install.html)
version 4 or greater
## Installation
JupyterHub can be installed with `pip` (and the proxy with `npm`) or `conda`:
**pip, npm:**
```bash
python3 -m pip install jupyterhub
npm install -g configurable-http-proxy
python3 -m pip install notebook # needed if running the notebook servers locally
```
**conda** (one command installs jupyterhub and proxy):
```bash
conda install -c conda-forge jupyterhub # installs jupyterhub and proxy
conda install notebook # needed if running the notebook servers locally
```
Test your installation. If installed, these commands should return the packages'
help contents:
```bash
jupyterhub -h
configurable-http-proxy -h
```
## Start the Hub server
To start the Hub server, run the command:
```bash
jupyterhub
```
Visit `https://localhost:8000` in your browser, and sign in with your unix
credentials.
To **allow multiple users to sign in** to the Hub server, you must start
`jupyterhub` as a *privileged user*, such as root:
```bash
sudo jupyterhub
```
The [wiki](https://github.com/jupyterhub/jupyterhub/wiki/Using-sudo-to-run-JupyterHub-without-root-privileges)
describes how to run the server as a *less privileged user*. This requires
additional configuration of the system.

View File

@@ -0,0 +1,222 @@
# Authenticators
The [Authenticator][] is the mechanism for authorizing users to use the
Hub and single user notebook servers.
## The default PAM Authenticator
JupyterHub ships only with the default [PAM][]-based Authenticator,
for logging in with local user accounts via a username and password.
## The OAuthenticator
Some login mechanisms, such as [OAuth][], don't map onto username and
password authentication, and instead use tokens. When using these
mechanisms, you can override the login handlers.
You can see an example implementation of an Authenticator that uses
[GitHub OAuth][] at [OAuthenticator][].
JupyterHub's [OAuthenticator][] currently supports the following
popular services:
- Auth0
- Bitbucket
- CILogon
- GitHub
- GitLab
- Globus
- Google
- MediaWiki
- Okpy
- OpenShift
A generic implementation, which you can use for OAuth authentication
with any provider, is also available.
## Additional Authenticators
- ldapauthenticator for LDAP
- tmpauthenticator for temporary accounts
## Technical Overview of Authentication
### How the Base Authenticator works
The base authenticator uses simple username and password authentication.
The base Authenticator has one central method:
#### Authenticator.authenticate method
Authenticator.authenticate(handler, data)
This method is passed the Tornado `RequestHandler` and the `POST data`
from JupyterHub's login form. Unless the login form has been customized,
`data` will have two keys:
- `username`
- `password`
The `authenticate` method's job is simple:
- return the username (non-empty str) of the authenticated user if
authentication is successful
- return `None` otherwise
Writing an Authenticator that looks up passwords in a dictionary
requires only overriding this one method:
```python
from tornado import gen
from IPython.utils.traitlets import Dict
from jupyterhub.auth import Authenticator
class DictionaryAuthenticator(Authenticator):
passwords = Dict(config=True,
help="""dict of username:password for authentication"""
)
@gen.coroutine
def authenticate(self, handler, data):
if self.passwords.get(data['username']) == data['password']:
return data['username']
```
#### Normalize usernames
Since the Authenticator and Spawner both use the same username,
sometimes you want to transform the name coming from the authentication service
(e.g. turning email addresses into local system usernames) before adding them to the Hub service.
Authenticators can define `normalize_username`, which takes a username.
The default normalization is to cast names to lowercase
For simple mappings, a configurable dict `Authenticator.username_map` is used to turn one name into another:
```python
c.Authenticator.username_map = {
'service-name': 'localname'
}
```
#### Validate usernames
In most cases, there is a very limited set of acceptable usernames.
Authenticators can define `validate_username(username)`,
which should return True for a valid username and False for an invalid one.
The primary effect this has is improving error messages during user creation.
The default behavior is to use configurable `Authenticator.username_pattern`,
which is a regular expression string for validation.
To only allow usernames that start with 'w':
```python
c.Authenticator.username_pattern = r'w.*'
```
### How to write a custom authenticator
You can use custom Authenticator subclasses to enable authentication
via other mechanisms. One such example is using [GitHub OAuth][].
Because the username is passed from the Authenticator to the Spawner,
a custom Authenticator and Spawner are often used together.
For example, the Authenticator methods, [pre_spawn_start(user, spawner)][]
and [post_spawn_stop(user, spawner)][], are hooks that can be used to do
auth-related startup (e.g. opening PAM sessions) and cleanup
(e.g. closing PAM sessions).
See a list of custom Authenticators [on the wiki](https://github.com/jupyterhub/jupyterhub/wiki/Authenticators).
If you are interested in writing a custom authenticator, you can read
[this tutorial](http://jupyterhub-tutorial.readthedocs.io/en/latest/authenticators.html).
### Authentication state
JupyterHub 0.8 adds the ability to persist state related to authentication,
such as auth-related tokens.
If such state should be persisted, `.authenticate()` should return a dictionary of the form:
```python
{
'username': 'name',
'auth_state': {
'key': 'value',
}
}
```
where `username` is the username that has been authenticated,
and `auth_state` is any JSON-serializable dictionary.
Because `auth_state` may contain sensitive information,
it is encrypted before being stored in the database.
To store auth_state, two conditions must be met:
1. persisting auth state must be enabled explicitly via configuration
```python
c.Authenticator.enable_auth_state = True
```
2. encryption must be enabled by the presence of `JUPYTERHUB_CRYPT_KEY` environment variable,
which should be a hex-encoded 32-byte key.
For example:
```bash
export JUPYTERHUB_CRYPT_KEY=$(openssl rand -hex 32)
```
JupyterHub uses [Fernet](https://cryptography.io/en/latest/fernet/) to encrypt auth_state.
To facilitate key-rotation, `JUPYTERHUB_CRYPT_KEY` may be a semicolon-separated list of encryption keys.
If there are multiple keys present, the **first** key is always used to persist any new auth_state.
#### Using auth_state
Typically, if `auth_state` is persisted it is desirable to affect the Spawner environment in some way.
This may mean defining environment variables, placing certificate in the user's home directory, etc.
The `Authenticator.pre_spawn_start` method can be used to pass information from authenticator state
to Spawner environment:
```python
class MyAuthenticator(Authenticator):
@gen.coroutine
def authenticate(self, handler, data=None):
username = yield identify_user(handler, data)
upstream_token = yield token_for_user(username)
return {
'username': username,
'auth_state': {
'upstream_token': upstream_token,
},
}
@gen.coroutine
def pre_spawn_start(self, user, spawner):
"""Pass upstream_token to spawner via environment variable"""
auth_state = yield user.get_auth_state()
if not auth_state:
# auth_state not enabled
return
spawner.environment['UPSTREAM_TOKEN'] = auth_state['upstream_token']
```
## JupyterHub as an OAuth provider
Beginning with version 0.8, JupyterHub is an OAuth provider.
[Authenticator]: https://github.com/jupyterhub/jupyterhub/blob/master/jupyterhub/auth.py
[PAM]: https://en.wikipedia.org/wiki/Pluggable_authentication_module
[OAuth]: https://en.wikipedia.org/wiki/OAuth
[GitHub OAuth]: https://developer.github.com/v3/oauth/
[OAuthenticator]: https://github.com/jupyterhub/oauthenticator
[pre_spawn_start(user, spawner)]: http://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.pre_spawn_start
[post_spawn_stop(user, spawner)]: http://jupyterhub.readthedocs.io/en/latest/api/auth.html#jupyterhub.auth.Authenticator.post_spawn_stop

View File

@@ -0,0 +1,272 @@
# Configuration examples
This section provides examples, including configuration files and tips, for the
following configurations:
- Using GitHub OAuth
- Using nginx reverse proxy
## Using GitHub OAuth
In this example, we show a configuration file for a fairly standard JupyterHub
deployment with the following assumptions:
* Running JupyterHub on a single cloud server
* Using SSL on the standard HTTPS port 443
* Using GitHub OAuth (using oauthenticator) for login
* Users exist locally on the server
* Users' notebooks to be served from `~/assignments` to allow users to browse
for notebooks within other users' home directories
* You want the landing page for each user to be a `Welcome.ipynb` notebook in
their assignments directory.
* All runtime files are put into `/srv/jupyterhub` and log files in `/var/log`.
The `jupyterhub_config.py` file would have these settings:
```python
# jupyterhub_config.py file
c = get_config()
import os
pjoin = os.path.join
runtime_dir = os.path.join('/srv/jupyterhub')
ssl_dir = pjoin(runtime_dir, 'ssl')
if not os.path.exists(ssl_dir):
os.makedirs(ssl_dir)
# Allows multiple single-server per user
c.JupyterHub.allow_named_servers = True
# https on :443
c.JupyterHub.port = 443
c.JupyterHub.ssl_key = pjoin(ssl_dir, 'ssl.key')
c.JupyterHub.ssl_cert = pjoin(ssl_dir, 'ssl.cert')
# put the JupyterHub cookie secret and state db
# in /var/run/jupyterhub
c.JupyterHub.cookie_secret_file = pjoin(runtime_dir, 'cookie_secret')
c.JupyterHub.db_url = pjoin(runtime_dir, 'jupyterhub.sqlite')
# or `--db=/path/to/jupyterhub.sqlite` on the command-line
# use GitHub OAuthenticator for local users
c.JupyterHub.authenticator_class = 'oauthenticator.LocalGitHubOAuthenticator'
c.GitHubOAuthenticator.oauth_callback_url = os.environ['OAUTH_CALLBACK_URL']
# create system users that don't exist yet
c.LocalAuthenticator.create_system_users = True
# specify users and admin
c.Authenticator.whitelist = {'rgbkrk', 'minrk', 'jhamrick'}
c.Authenticator.admin_users = {'jhamrick', 'rgbkrk'}
# start single-user notebook servers in ~/assignments,
# with ~/assignments/Welcome.ipynb as the default landing page
# this config could also be put in
# /etc/jupyter/jupyter_notebook_config.py
c.Spawner.notebook_dir = '~/assignments'
c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
```
Using the GitHub Authenticator requires a few additional
environment variable to be set prior to launching JupyterHub:
```bash
export GITHUB_CLIENT_ID=github_id
export GITHUB_CLIENT_SECRET=github_secret
export OAUTH_CALLBACK_URL=https://example.com/hub/oauth_callback
export CONFIGPROXY_AUTH_TOKEN=super-secret
# append log output to log file /var/log/jupyterhub.log
jupyterhub -f /etc/jupyterhub/jupyterhub_config.py &>> /var/log/jupyterhub.log
```
## Using a reverse proxy
In the following example, we show configuration files for a JupyterHub server
running locally on port `8000` but accessible from the outside on the standard
SSL port `443`. This could be useful if the JupyterHub server machine is also
hosting other domains or content on `443`. The goal in this example is to
satisfy the following:
* JupyterHub is running on a server, accessed *only* via `HUB.DOMAIN.TLD:443`
* On the same machine, `NO_HUB.DOMAIN.TLD` strictly serves different content,
also on port `443`
* `nginx` or `apache` is used as the public access point (which means that
only nginx/apache will bind to `443`)
* After testing, the server in question should be able to score at least an A on the
Qualys SSL Labs [SSL Server Test](https://www.ssllabs.com/ssltest/)
Let's start out with needed JupyterHub configuration in `jupyterhub_config.py`:
```python
# Force the proxy to only listen to connections to 127.0.0.1
c.JupyterHub.ip = '127.0.0.1'
```
For high-quality SSL configuration, we also generate Diffie-Helman parameters.
This can take a few minutes:
```bash
openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
```
### nginx
The **`nginx` server config file** is fairly standard fare except for the two
`location` blocks within the `HUB.DOMAIN.TLD` config file:
```bash
# top-level http config for websocket headers
# If Upgrade is defined, Connection = upgrade
# If Upgrade is empty, Connection = close
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP server to redirect all 80 traffic to SSL/HTTPS
server {
listen 80;
server_name HUB.DOMAIN.TLD;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
# HTTPS server to handle JupyterHub
server {
listen 443;
ssl on;
server_name HUB.DOMAIN.TLD;
ssl_certificate /etc/letsencrypt/live/HUB.DOMAIN.TLD/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/HUB.DOMAIN.TLD/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security max-age=15768000;
# Managing literal requests to the JupyterHub front end
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# websocket headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# Managing requests to verify letsencrypt host
location ~ /.well-known {
allow all;
}
}
```
If `nginx` is not running on port 443, substitute `$http_host` for `$host` on
the lines setting the `Host` header.
`nginx` will now be the front facing element of JupyterHub on `443` which means
it is also free to bind other servers, like `NO_HUB.DOMAIN.TLD` to the same port
on the same machine and network interface. In fact, one can simply use the same
server blocks as above for `NO_HUB` and simply add line for the root directory
of the site as well as the applicable location call:
```bash
server {
listen 80;
server_name NO_HUB.DOMAIN.TLD;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
server {
listen 443;
ssl on;
# INSERT OTHER SSL PARAMETERS HERE AS ABOVE
# SSL cert may differ
# Set the appropriate root directory
root /var/www/html
# Set URI handling
location / {
try_files $uri $uri/ =404;
}
# Managing requests to verify letsencrypt host
location ~ /.well-known {
allow all;
}
}
```
Now restart `nginx`, restart the JupyterHub, and enjoy accessing
`https://HUB.DOMAIN.TLD` while serving other content securely on
`https://NO_HUB.DOMAIN.TLD`.
### Apache
As with nginx above, you can use [Apache](https://httpd.apache.org) as the reverse proxy.
First, we will need to enable the apache modules that we are going to need:
```bash
a2enmod ssl rewrite proxy proxy_http proxy_wstunnel
```
Our Apache configuration is equivalent to the nginx configuration above:
- Redirect HTTP to HTTPS
- Good SSL Configuration
- Support for websockets on any proxied URL
- JupyterHub is running locally at http://127.0.0.1:8000
```bash
# redirect HTTP to HTTPS
Listen 80
<VirtualHost HUB.DOMAIN.TLD:80>
ServerName HUB.DOMAIN.TLD
Redirect / https://HUB.DOMAIN.TLD/
</VirtualHost>
Listen 443
<VirtualHost HUB.DOMAIN.TLD:443>
ServerName HUB.DOMAIN.TLD
# configure SSL
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/HUB.DOMAIN.TLD/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/HUB.DOMAIN.TLD/privkey.pem
SSLProtocol All -SSLv2 -SSLv3
SSLOpenSSLConfCmd DHParameters /etc/ssl/certs/dhparam.pem
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
# Use RewriteEngine to handle websocket connection upgrades
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:8000/$1 [P,L]
<Location "/">
# preserve Host header to avoid cross-origin problems
ProxyPreserveHost on
# proxy to JupyterHub
ProxyPass http://127.0.0.1:8000/
ProxyPassReverse http://127.0.0.1:8000/
</Location>
</VirtualHost>
```

View File

@@ -0,0 +1,15 @@
Technical Reference
===================
.. toctree::
:maxdepth: 2
technical-overview
websecurity
authenticators
spawners
services
proxy
rest
upgrading
config-examples

View File

@@ -0,0 +1,183 @@
# Writing a custom Proxy implementation
JupyterHub 0.8 introduced the ability to write a custom implementation of the proxy.
This enables deployments with different needs than the default proxy,
configurable-http-proxy (CHP).
CHP is a single-process nodejs proxy that they Hub manages by default as a subprocess
(it can be run externally, as well, and typically is in production deployments).
The upside to CHP, and why we use it by default, is that it's easy to install and run (if you have nodejs, you are set!).
The downsides are that it's a single process and does not support any persistence of the routing table.
So if the proxy process dies, your whole JupyterHub instance is inaccessible until the Hub notices, restarts the proxy, and restores the routing table.
For deployments that want to avoid such a single point of failure,
or leverage existing proxy infrastructure in their chosen deployment (such as Kubernetes ingress objects),
the Proxy API provides a way to do that.
In general, for a proxy to be usable by JupyterHub, it must:
1. support websockets without prior knowledge of the URL where websockets may occur
2. support trie-based routing (i.e. allow different routes on `/foo` and `/foo/bar` and route based on specificity)
3. adding or removing a route should not cause existing connections to drop
Optionally, if the JupyterHub deployment is to use host-based routing,
the Proxy must additionally support routing based on the Host of the request.
## Subclassing Proxy
To start, any Proxy implementation should subclass the base Proxy class,
as is done with custom Spawners and Authenticators.
```python
from jupyterhub.proxy import Proxy
class MyProxy(Proxy):
"""My Proxy implementation"""
...
```
## Starting and stopping the proxy
If your proxy should be launched when the Hub starts, you must define how to start and stop your proxy:
```python
from tornado import gen
class MyProxy(Proxy):
...
@gen.coroutine
def start(self):
"""Start the proxy"""
@gen.coroutine
def stop(self):
"""Stop the proxy"""
```
These methods **may** be coroutines.
`c.Proxy.should_start` is a configurable flag that determines whether the Hub should call these methods when the Hub itself starts and stops.
### Purely external proxies
Probably most custom proxies will be externally managed,
such as Kubernetes ingress-based implementations.
In this case, you do not need to define `start` and `stop`.
To disable the methods, you can define `should_start = False` at the class level:
```python
class MyProxy(Proxy):
should_start = False
```
## Adding and removing routes
At its most basic, a Proxy implementation defines a mechanism to add, remove, and retrieve routes.
A proxy that implements these three methods is complete.
Each of these methods **may** be a coroutine.
**Definition:** routespec
A routespec, which will appear in these methods, is a string describing a route to be proxied,
such as `/user/name/`. A routespec will:
1. always end with `/`
2. always start with `/` if it is a path-based route `/proxy/path/`
3. precede the leading `/` with a host for host-based routing, e.g. `host.tld/proxy/path/`
### Adding a route
When adding a route, JupyterHub may pass a JSON-serializable dict as a `data` argument
that should be attacked to the proxy route.
When that route is retrieved, the `data` argument should be returned as well.
If your proxy implementation doesn't support storing data attached to routes,
then your Python wrapper may have to handle storing the `data` piece itself,
e.g in a simple file or database.
```python
@gen.coroutine
def add_route(self, routespec, target, data):
"""Proxy `routespec` to `target`.
Store `data` associated with the routespec
for retrieval later.
"""
```
Adding a route for a user looks like this:
```python
proxy.add_route('/user/pgeorgiou/', 'http://127.0.0.1:1227',
{'user': 'pgeorgiou'})
```
### Removing routes
`delete_route()` is given a routespec to delete.
If there is no such route, `delete_route` should still succeed,
but a warning may be issued.
```python
@gen.coroutine
def delete_route(self, routespec):
"""Delete the route"""
```
### Retrieving routes
For retrieval, you only *need* to implement a single method that retrieves all routes.
The return value for this function should be a dictionary, keyed by `routespect`,
of dicts whose keys are the same three arguments passed to `add_route`
(`routespec`, `target`, `data`)
```python
@gen.coroutine
def get_all_routes(self):
"""Return all routes, keyed by routespec""""
```
```python
{
'/proxy/path/': {
'routespec': '/proxy/path/',
'target': 'http://...',
'data': {},
},
}
```
#### Note on activity tracking
JupyterHub can track activity of users, for use in services such as culling idle servers.
As of JupyterHub 0.8, this activity tracking is the responsibility of the proxy.
If your proxy implementation can track activity to endpoints,
it may add a `last_activity` key to the `data` of routes retrieved in `.get_all_routes()`.
If present, the value of `last_activity` should be an [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) UTC date string:
```python
{
'/user/pgeorgiou/': {
'routespec': '/user/pgeorgiou/',
'target': 'http://127.0.0.1:1227',
'data': {
'user': 'pgeourgiou',
'last_activity': '2017-10-03T10:33:49.570Z',
},
},
}
```
If the proxy does not track activity, then only activity to the Hub itself is tracked,
and services such as cull-idle will not work.
Now that `notebook-5.0` tracks activity internally,
we can retrieve activity information from the single-user servers instead,
removing the need to track activity in the proxy.
But this is not yet implemented in JupyterHub 0.8.0.

View File

@@ -0,0 +1,181 @@
# Using JupyterHub's REST API
This section will give you information on:
- what you can do with the API
- create an API token
- add API tokens to the config files
- make an API request programmatically using the requests library
- learn more about JupyterHub's API
## What you can do with the API
Using the [JupyterHub REST API][], you can perform actions on the Hub,
such as:
- checking which users are active
- adding or removing users
- stopping or starting single user notebook servers
- authenticating services
A [REST](https://en.wikipedia.org/wiki/Representational_state_transfer)
API provides a standard way for users to get and send information to the
Hub.
## Create an API token
To send requests using JupyterHub API, you must pass an API token with
the request.
As of [version 0.6.0](../changelog.html), the preferred way of
generating an API token is:
```bash
openssl rand -hex 32
```
This `openssl` command generates a potential token that can then be
added to JupyterHub using `.api_tokens` configuration setting in
`jupyterhub_config.py`.
Alternatively, use the `jupyterhub token` command to generate a token
for a specific hub user by passing the 'username':
```bash
jupyterhub token <username>
```
This command generates a random string to use as a token and registers
it for the given user with the Hub's database.
In [version 0.8.0](../changelog.html), a TOKEN request page for
generating an API token is available from the JupyterHub user interface:
![Request API TOKEN page](../images/token-request.png)
![API TOKEN success page](../images/token-request-success.png)
## Add API tokens to the config file
You may also add a dictionary of API tokens and usernames to the hub's
configuration file, `jupyterhub_config.py` (note that
the **key** is the 'secret-token' while the **value** is the 'username'):
```python
c.JupyterHub.api_tokens = {
'secret-token': 'username',
}
```
## Make an API request
To authenticate your requests, pass the API token in the request's
Authorization header.
### Use requests
Using the popular Python [requests](http://docs.python-requests.org/en/master/)
library, here's example code to make an API request for the users of a JupyterHub
deployment. An API GET request is made, and the request sends an API token for
authorization. The response contains information about the users:
```python
import requests
api_url = 'http://127.0.0.1:8081/hub/api'
r = requests.get(api_url + '/users',
headers={
'Authorization': 'token %s' % token,
}
)
r.raise_for_status()
users = r.json()
```
This example provides a slightly more complicated request, yet the
process is very similar:
```python
import requests
api_url = 'http://127.0.0.1:8081/hub/api'
data = {'name': 'mygroup', 'users': ['user1', 'user2']}
r = requests.post(api_url + '/groups/formgrade-data301/users',
headers={
'Authorization': 'token %s' % token,
},
json=data
)
r.raise_for_status()
r.json()
```
Note that the API token authorizes **JupyterHub** REST API requests. The same
token does **not** authorize access to the [Jupyter Notebook REST API][]
provided by notebook servers managed by JupyterHub. A different token is used
to access the **Jupyter Notebook** API.
## Enabling users to spawn multiple named-servers via the API
With JupyterHub version 0.8, support for multiple servers per user has landed.
Prior to that, each user could only launch a single default server via the API
like this:
```bash
curl -X POST -H "Authorization: token <token>" "http://127.0.0.1:8081/hub/api/users/<user>/server"
```
With the named-server functionality, it's now possible to launch more than one
specifically named servers against a given user. This could be used, for instance,
to launch each server based on a different image.
First you must enable named-servers by including the following setting in the `jupyterhub_config.py` file.
`c.JupyterHub.allow_named_servers = True`
If using the [zero-to-jupyterhub-k8s](https://github.com/jupyterhub/zero-to-jupyterhub-k8s) set-up to run JupyterHub,
then instead of editing the `jupyterhub_config.py` file directly, you could pass
the following as part of the `config.yaml` file, as per the [tutorial](https://zero-to-jupyterhub.readthedocs.io/en/latest/):
```bash
hub:
extraConfig: |
c.JupyterHub.allow_named_servers = True
```
With that setting in place, a new named-server is activated like this:
```bash
curl -X POST -H "Authorization: token <token>" "http://127.0.0.1:8081/hub/api/users/<user>/servers/<serverA>"
curl -X POST -H "Authorization: token <token>" "http://127.0.0.1:8081/hub/api/users/<user>/servers/<serverB>"
```
The same servers can be stopped by substituting `DELETE` for `POST` above.
### Some caveats for using named-servers
The named-server capabilities are not fully implemented for JupyterHub as yet.
While it's possible to start/stop a server via the API, the UI on the
JupyterHub control-panel has not been implemented, and so it may not be obvious
to those viewing the panel that a named-server may be running for a given user.
For named-servers via the API to work, the spawner used to spawn these servers
will need to be able to handle the case of multiple servers per user and ensure
uniqueness of names, particularly if servers are spawned via docker containers
or kubernetes pods.
## Learn more about the API
You can see the full [JupyterHub REST API][] for details. This REST API Spec can
be viewed in a more [interactive style on swagger's petstore][].
Both resources contain the same information and differ only in its display.
Note: The Swagger specification is being renamed the [OpenAPI Initiative][].
[interactive style on swagger's petstore]: http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyterhub/jupyterhub/master/docs/rest-api.yml#!/default
[OpenAPI Initiative]: https://www.openapis.org/
[JupyterHub REST API]: ../_static/rest-api/index.html
[Jupyter Notebook REST API]: http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml

View File

@@ -0,0 +1,366 @@
# Services
With version 0.7, JupyterHub adds support for **Services**.
This section provides the following information about Services:
- [Definition of a Service](#definition-of-a-service)
- [Properties of a Service](#properties-of-a-service)
- [Hub-Managed Services](#hub-managed-services)
- [Launching a Hub-Managed Service](#launching-a-hub-managed-service)
- [Externally-Managed Services](#externally-managed-services)
- [Writing your own Services](#writing-your-own-services)
- [Hub Authentication and Services](#hub-authentication-and-services)
## Definition of a Service
When working with JupyterHub, a **Service** is defined as a process that interacts
with the Hub's REST API. A Service may perform a specific or
action or task. For example, the following tasks can each be a unique Service:
- shutting down individuals' single user notebook servers that have been idle
for some time
- registering additional web servers which should use the Hub's authentication
and be served behind the Hub's proxy.
Two key features help define a Service:
- Is the Service **managed** by JupyterHub?
- Does the Service have a web server that should be added to the proxy's
table?
Currently, these characteristics distinguish two types of Services:
- A **Hub-Managed Service** which is managed by JupyterHub
- An **Externally-Managed Service** which runs its own web server and
communicates operation instructions via the Hub's API.
## Properties of a Service
A Service may have the following properties:
- `name: str` - the name of the service
- `admin: bool (default - false)` - whether the service should have
administrative privileges
- `url: str (default - None)` - The URL where the service is/should be. If a
url is specified for where the Service runs its own web server,
the service will be added to the proxy at `/services/:name`
- `api_token: str (default - None)` - For Externally-Managed Services you need to specify
an API token to perform API requests to the Hub
If a service is also to be managed by the Hub, it has a few extra options:
- `command: (str/Popen list`) - Command for JupyterHub to spawn the service.
- Only use this if the service should be a subprocess.
- If command is not specified, the Service is assumed to be managed
externally.
- If a command is specified for launching the Service, the Service will
be started and managed by the Hub.
- `environment: dict` - additional environment variables for the Service.
- `user: str` - the name of a system user to manage the Service. If
unspecified, run as the same user as the Hub.
## Hub-Managed Services
A **Hub-Managed Service** is started by the Hub, and the Hub is responsible
for the Service's actions. A Hub-Managed Service can only be a local
subprocess of the Hub. The Hub will take care of starting the process and
restarts it if it stops.
While Hub-Managed Services share some similarities with notebook Spawners,
there are no plans for Hub-Managed Services to support the same spawning
abstractions as a notebook Spawner.
If you wish to run a Service in a Docker container or other deployment
environments, the Service can be registered as an
**Externally-Managed Service**, as described below.
## Launching a Hub-Managed Service
A Hub-Managed Service is characterized by its specified `command` for launching
the Service. For example, a 'cull idle' notebook server task configured as a
Hub-Managed Service would include:
- the Service name,
- admin permissions, and
- the `command` to launch the Service which will cull idle servers after a
timeout interval
This example would be configured as follows in `jupyterhub_config.py`:
```python
c.JupyterHub.services = [
{
'name': 'cull-idle',
'admin': True,
'command': ['python', '/path/to/cull-idle.py', '--timeout']
}
]
```
A Hub-Managed Service may also be configured with additional optional
parameters, which describe the environment needed to start the Service process:
- `environment: dict` - additional environment variables for the Service.
- `user: str` - name of the user to run the server if different from the Hub.
Requires Hub to be root.
- `cwd: path` directory in which to run the Service, if different from the
Hub directory.
The Hub will pass the following environment variables to launch the Service:
```bash
JUPYTERHUB_SERVICE_NAME: The name of the service
JUPYTERHUB_API_TOKEN: API token assigned to the service
JUPYTERHUB_API_URL: URL for the JupyterHub API (default, http://127.0.0.1:8080/hub/api)
JUPYTERHUB_BASE_URL: Base URL of the Hub (https://mydomain[:port]/)
JUPYTERHUB_SERVICE_PREFIX: URL path prefix of this service (/services/:service-name/)
JUPYTERHUB_SERVICE_URL: Local URL where the service is expected to be listening.
Only for proxied web services.
```
For the previous 'cull idle' Service example, these environment variables
would be passed to the Service when the Hub starts the 'cull idle' Service:
```bash
JUPYTERHUB_SERVICE_NAME: 'cull-idle'
JUPYTERHUB_API_TOKEN: API token assigned to the service
JUPYTERHUB_API_URL: http://127.0.0.1:8080/hub/api
JUPYTERHUB_BASE_URL: https://mydomain[:port]
JUPYTERHUB_SERVICE_PREFIX: /services/cull-idle/
```
See the JupyterHub GitHub repo for additional information about the
[`cull-idle` example](https://github.com/jupyterhub/jupyterhub/tree/master/examples/cull-idle).
## Externally-Managed Services
You may prefer to use your own service management tools, such as Docker or
systemd, to manage a JupyterHub Service. These **Externally-Managed
Services**, unlike Hub-Managed Services, are not subprocesses of the Hub. You
must tell JupyterHub which API token the Externally-Managed Service is using
to perform its API requests. Each Externally-Managed Service will need a
unique API token, because the Hub authenticates each API request and the API
token is used to identify the originating Service or user.
A configuration example of an Externally-Managed Service with admin access and
running its own web server is:
```python
c.JupyterHub.services = [
{
'name': 'my-web-service',
'url': 'https://10.0.1.1:1984',
'api_token': 'super-secret',
}
]
```
In this case, the `url` field will be passed along to the Service as
`JUPYTERHUB_SERVICE_URL`.
## Writing your own Services
When writing your own services, you have a few decisions to make (in addition
to what your service does!):
1. Does my service need a public URL?
2. Do I want JupyterHub to start/stop the service?
3. Does my service need to authenticate users?
When a Service is managed by JupyterHub, the Hub will pass the necessary
information to the Service via the environment variables described above. A
flexible Service, whether managed by the Hub or not, can make use of these
same environment variables.
When you run a service that has a url, it will be accessible under a
`/services/` prefix, such as `https://myhub.horse/services/my-service/`. For
your service to route proxied requests properly, it must take
`JUPYTERHUB_SERVICE_PREFIX` into account when routing requests. For example, a
web service would normally service its root handler at `'/'`, but the proxied
service would need to serve `JUPYTERHUB_SERVICE_PREFIX + '/'`.
## Hub Authentication and Services
JupyterHub 0.7 introduces some utilities for using the Hub's authentication
mechanism to govern access to your service. When a user logs into JupyterHub,
the Hub sets a **cookie (`jupyterhub-services`)**. The service can use this
cookie to authenticate requests.
JupyterHub ships with a reference implementation of Hub authentication that
can be used by services. You may go beyond this reference implementation and
create custom hub-authenticating clients and services. We describe the process
below.
The reference, or base, implementation is the [`HubAuth`][HubAuth] class,
which implements the requests to the Hub.
To use HubAuth, you must set the `.api_token`, either programmatically when constructing the class,
or via the `JUPYTERHUB_API_TOKEN` environment variable.
Most of the logic for authentication implementation is found in the
[`HubAuth.user_for_cookie`](services.auth.html#jupyterhub.services.auth.HubAuth.user_for_cookie)
and in the
[`HubAuth.user_for_token`](services.auth.html#jupyterhub.services.auth.HubAuth.user_for_token)
methods, which makes a request of the Hub, and returns:
- None, if no user could be identified, or
- a dict of the following form:
```python
{
"name": "username",
"groups": ["list", "of", "groups"],
"admin": False, # or True
}
```
You are then free to use the returned user information to take appropriate
action.
HubAuth also caches the Hub's response for a number of seconds,
configurable by the `cookie_cache_max_age` setting (default: five minutes).
### Flask Example
For example, you have a Flask service that returns information about a user.
JupyterHub's HubAuth class can be used to authenticate requests to the Flask
service. See the `service-whoami-flask` example in the
[JupyterHub GitHub repo](https://github.com/jupyterhub/jupyterhub/tree/master/examples/service-whoami-flask)
for more details.
```python
from functools import wraps
import json
import os
from urllib.parse import quote
from flask import Flask, redirect, request, Response
from jupyterhub.services.auth import HubAuth
prefix = os.environ.get('JUPYTERHUB_SERVICE_PREFIX', '/')
auth = HubAuth(
api_token=os.environ['JUPYTERHUB_API_TOKEN'],
cookie_cache_max_age=60,
)
app = Flask(__name__)
def authenticated(f):
"""Decorator for authenticating with the Hub"""
@wraps(f)
def decorated(*args, **kwargs):
cookie = request.cookies.get(auth.cookie_name)
token = request.headers.get(auth.auth_header_name)
if cookie:
user = auth.user_for_cookie(cookie)
elif token:
user = auth.user_for_token(token)
else:
user = None
if user:
return f(user, *args, **kwargs)
else:
# redirect to login url on failed auth
return redirect(auth.login_url + '?next=%s' % quote(request.path))
return decorated
@app.route(prefix + '/')
@authenticated
def whoami(user):
return Response(
json.dumps(user, indent=1, sort_keys=True),
mimetype='application/json',
)
```
### Authenticating tornado services with JupyterHub
Since most Jupyter services are written with tornado,
we include a mixin class, [`HubAuthenticated`][HubAuthenticated],
for quickly authenticating your own tornado services with JupyterHub.
Tornado's `@web.authenticated` method calls a Handler's `.get_current_user`
method to identify the user. Mixing in `HubAuthenticated` defines
`get_current_user` to use HubAuth. If you want to configure the HubAuth
instance beyond the default, you'll want to define an `initialize` method,
such as:
```python
class MyHandler(HubAuthenticated, web.RequestHandler):
hub_users = {'inara', 'mal'}
def initialize(self, hub_auth):
self.hub_auth = hub_auth
@web.authenticated
def get(self):
...
```
The HubAuth will automatically load the desired configuration from the Service
environment variables.
If you want to limit user access, you can whitelist users through either the
`.hub_users` attribute or `.hub_groups`. These are sets that check against the
username and user group list, respectively. If a user matches neither the user
list nor the group list, they will not be allowed access. If both are left
undefined, then any user will be allowed.
### Implementing your own Authentication with JupyterHub
If you don't want to use the reference implementation
(e.g. you find the implementation a poor fit for your Flask app),
you can implement authentication via the Hub yourself.
We recommend looking at the [`HubAuth`][HubAuth] class implementation for reference,
and taking note of the following process:
1. retrieve the cookie `jupyterhub-services` from the request.
2. Make an API request `GET /hub/api/authorizations/cookie/jupyterhub-services/cookie-value`,
where cookie-value is the url-encoded value of the `jupyterhub-services` cookie.
This request must be authenticated with a Hub API token in the `Authorization` header.
For example, with [requests][]:
```python
r = requests.get(
'/'.join((["http://127.0.0.1:8081/hub/api",
"authorizations/cookie/jupyterhub-services",
quote(encrypted_cookie, safe=''),
]),
headers = {
'Authorization' : 'token %s' % api_token,
},
)
r.raise_for_status()
user = r.json()
```
3. On success, the reply will be a JSON model describing the user:
```json
{
"name": "inara",
"groups": ["serenity", "guild"],
}
```
An example of using an Externally-Managed Service and authentication is
in [nbviewer README]_ section on securing the notebook viewer,
and an example of its configuration is found [here](https://github.com/jupyter/nbviewer/blob/master/nbviewer/providers/base.py#L94).
nbviewer can also be run as a Hub-Managed Service as described [nbviewer README]_
section on securing the notebook viewer.
[requests]: http://docs.python-requests.org/en/master/
[services_auth]: ../api/services.auth.html
[HubAuth]: ../api/services.auth.html#jupyterhub.services.auth.HubAuth
[HubAuthenticated]: ../api/services.auth.html#jupyterhub.services.auth.HubAuthenticated
[nbviewer example]: https://github.com/jupyter/nbviewer#securing-the-notebook-viewer

View File

@@ -0,0 +1,213 @@
# Spawners
A [Spawner][] starts each single-user notebook server.
The Spawner represents an abstract interface to a process,
and a custom Spawner needs to be able to take three actions:
- start the process
- poll whether the process is still running
- stop the process
## Examples
Custom Spawners for JupyterHub can be found on the [JupyterHub wiki](https://github.com/jupyterhub/jupyterhub/wiki/Spawners).
Some examples include:
- [DockerSpawner](https://github.com/jupyterhub/dockerspawner) for spawning user servers in Docker containers
* `dockerspawner.DockerSpawner` for spawning identical Docker containers for
each users
* `dockerspawner.SystemUserSpawner` for spawning Docker containers with an
environment and home directory for each users
* both `DockerSpawner` and `SystemUserSpawner` also work with Docker Swarm for
launching containers on remote machines
- [SudoSpawner](https://github.com/jupyterhub/sudospawner) enables JupyterHub to
run without being root, by spawning an intermediate process via `sudo`
- [BatchSpawner](https://github.com/jupyterhub/batchspawner) for spawning remote
servers using batch systems
- [RemoteSpawner](https://github.com/zonca/remotespawner) to spawn notebooks
and a remote server and tunnel the port via SSH
## Spawner control methods
### Spawner.start
`Spawner.start` should start the single-user server for a single user.
Information about the user can be retrieved from `self.user`,
an object encapsulating the user's name, authentication, and server info.
The return value of `Spawner.start` should be the (ip, port) of the running server.
**NOTE:** When writing coroutines, *never* `yield` in between a database change and a commit.
Most `Spawner.start` functions will look similar to this example:
```python
def start(self):
self.ip = '127.0.0.1'
self.port = random_port()
yield self._actually_start_server_somehow()
return (self.ip, self.port)
```
When `Spawner.start` returns, the single-user server process should actually be running,
not just requested. JupyterHub can handle `Spawner.start` being very slow
(such as PBS-style batch queues, or instantiating whole AWS instances)
via relaxing the `Spawner.start_timeout` config value.
### Spawner.poll
`Spawner.poll` should check if the spawner is still running.
It should return `None` if it is still running,
and an integer exit status, otherwise.
For the local process case, `Spawner.poll` uses `os.kill(PID, 0)`
to check if the local process is still running.
### Spawner.stop
`Spawner.stop` should stop the process. It must be a tornado coroutine, which should return when the process has finished exiting.
## Spawner state
JupyterHub should be able to stop and restart without tearing down
single-user notebook servers. To do this task, a Spawner may need to persist
some information that can be restored later.
A JSON-able dictionary of state can be used to store persisted information.
Unlike start, stop, and poll methods, the state methods must not be coroutines.
For the single-process case, the Spawner state is only the process ID of the server:
```python
def get_state(self):
"""get the current state"""
state = super().get_state()
if self.pid:
state['pid'] = self.pid
return state
def load_state(self, state):
"""load state from the database"""
super().load_state(state)
if 'pid' in state:
self.pid = state['pid']
def clear_state(self):
"""clear any state (called after shutdown)"""
super().clear_state()
self.pid = 0
```
## Spawner options form
(new in 0.4)
Some deployments may want to offer options to users to influence how their servers are started.
This may include cluster-based deployments, where users specify what resources should be available,
or docker-based deployments where users can select from a list of base images.
This feature is enabled by setting `Spawner.options_form`, which is an HTML form snippet
inserted unmodified into the spawn form.
If the `Spawner.options_form` is defined, when a user tries to start their server, they will be directed to a form page, like this:
![spawn-form](../images/spawn-form.png)
If `Spawner.options_form` is undefined, the user's server is spawned directly, and no spawn page is rendered.
See [this example](https://github.com/jupyterhub/jupyterhub/blob/master/examples/spawn-form/jupyterhub_config.py) for a form that allows custom CLI args for the local spawner.
### `Spawner.options_from_form`
Options from this form will always be a dictionary of lists of strings, e.g.:
```python
{
'integer': ['5'],
'text': ['some text'],
'select': ['a', 'b'],
}
```
When `formdata` arrives, it is passed through `Spawner.options_from_form(formdata)`,
which is a method to turn the form data into the correct structure.
This method must return a dictionary, and is meant to interpret the lists-of-strings into the correct types. For example, the `options_from_form` for the above form would look like:
```python
def options_from_form(self, formdata):
options = {}
options['integer'] = int(formdata['integer'][0]) # single integer value
options['text'] = formdata['text'][0] # single string value
options['select'] = formdata['select'] # list already correct
options['notinform'] = 'extra info' # not in the form at all
return options
```
which would return:
```python
{
'integer': 5,
'text': 'some text',
'select': ['a', 'b'],
'notinform': 'extra info',
}
```
When `Spawner.start` is called, this dictionary is accessible as `self.user_options`.
[Spawner]: https://github.com/jupyterhub/jupyterhub/blob/master/jupyterhub/spawner.py
## Writing a custom spawner
If you are interested in building a custom spawner, you can read [this tutorial](http://jupyterhub-tutorial.readthedocs.io/en/latest/spawners.html).
## Spawners, resource limits, and guarantees (Optional)
Some spawners of the single-user notebook servers allow setting limits or
guarantees on resources, such as CPU and memory. To provide a consistent
experience for sysadmins and users, we provide a standard way to set and
discover these resource limits and guarantees, such as for memory and CPU. For
the limits and guarantees to be useful, the spawner must implement support for
them.
### Memory Limits & Guarantees
`c.Spawner.mem_limit`: A **limit** specifies the *maximum amount of memory*
that may be allocated, though there is no promise that the maximum amount will
be available. In supported spawners, you can set `c.Spawner.mem_limit` to
limit the total amount of memory that a single-user notebook server can
allocate. Attempting to use more memory than this limit will cause errors. The
single-user notebook server can discover its own memory limit by looking at
the environment variable `MEM_LIMIT`, which is specified in absolute bytes.
`c.Spawner.mem_guarantee`: Sometimes, a **guarantee** of a *minumum amount of
memory* is desirable. In this case, you can set `c.Spawner.mem_guarantee` to
to provide a guarantee that at minimum this much memory will always be
available for the single-user notebook server to use. The environment variable
`MEM_GUARANTEE` will also be set in the single-user notebook server.
The spawner's underlying system or cluster is responsible for enforcing these
limits and providing these guarantees. If these values are set to `None`, no
limits or guarantees are provided, and no environment values are set.
### CPU Limits & Guarantees
`c.Spawner.cpu_limit`: In supported spawners, you can set
`c.Spawner.cpu_limit` to limit the total number of cpu-cores that a
single-user notebook server can use. These can be fractional - `0.5` means 50%
of one CPU core, `4.0` is 4 cpu-cores, etc. This value is also set in the
single-user notebook server's environment variable `CPU_LIMIT`. The limit does
not claim that you will be able to use all the CPU up to your limit as other
higher priority applications might be taking up CPU.
`c.Spawner.cpu_guarantee`: You can set `c.Spawner.cpu_guarantee` to provide a
guarantee for CPU usage. The environment variable `CPU_GUARANTEE` will be set
in the single-user notebook server when a guarantee is being provided.
The spawner's underlying system or cluster is responsible for enforcing these
limits and providing these guarantees. If these values are set to `None`, no
limits or guarantees are provided, and no environment values are set.

View File

@@ -0,0 +1,133 @@
# Technical Overview
The **Technical Overview** section gives you a high-level view of:
- JupyterHub's Subsystems: Hub, Proxy, Single-User Notebook Server
- how the subsystems interact
- the process from JupyterHub access to user login
- JupyterHub's default behavior
- customizing JupyterHub
The goal of this section is to share a deeper technical understanding of
JupyterHub and how it works.
## The Subsystems: Hub, Proxy, Single-User Notebook Server
JupyterHub is a set of processes that together provide a single user Jupyter
Notebook server for each person in a group. Three major subsystems are started
by the `jupyterhub` command line program:
- **Hub** (Python/Tornado): manages user accounts, authentication, and
coordinates Single User Notebook Servers using a Spawner.
- **Proxy**: the public facing part of JupyterHub that uses a dynamic proxy
to route HTTP requests to the Hub and Single User Notebook Servers.
[configurable http proxy](https://github.com/jupyterhub/configurable-http-proxy)
(node-http-proxy) is the default proxy.
- **Single-User Notebook Server** (Python/Tornado): a dedicated,
single-user, Jupyter Notebook server is started for each user on the system
when the user logs in. The object that starts the single-user notebook
servers is called a **Spawner**.
![JupyterHub subsystems](../images/jhub-parts.png)
## How the Subsystems Interact
Users access JupyterHub through a web browser, by going to the IP address or
the domain name of the server.
The basic principles of operation are:
- The Hub spawns the proxy (in the default JupyterHub configuration)
- The proxy forwards all requests to the Hub by default
- The Hub handles login, and spawns single-user notebook servers on demand
- The Hub configures the proxy to forward url prefixes to single-user notebook
servers
The proxy is the only process that listens on a public interface. The Hub sits
behind the proxy at `/hub`. Single-user servers sit behind the proxy at
`/user/[username]`.
Different **[authenticators](./authenticators.html)** control access
to JupyterHub. The default one (PAM) uses the user accounts on the server where
JupyterHub is running. If you use this, you will need to create a user account
on the system for each user on your team. Using other authenticators, you can
allow users to sign in with e.g. a GitHub account, or with any single-sign-on
system your organization has.
Next, **[spawners](./spawners.html)** control how JupyterHub starts
the individual notebook server for each user. The default spawner will
start a notebook server on the same machine running under their system username.
The other main option is to start each server in a separate container, often
using Docker.
## The Process from JupyterHub Access to User Login
When a user accesses JupyterHub, the following events take place:
- Login data is handed to the [Authenticator](./authenticators.html) instance for
validation
- The Authenticator returns the username if the login information is valid
- A single-user notebook server instance is [spawned](./spawners.html) for the
logged-in user
- When the single-user notebook server starts, the proxy is notified to forward
requests to `/user/[username]/*` to the single-user notebook server.
- A cookie is set on `/hub/`, containing an encrypted token. (Prior to version
0.8, a cookie for `/user/[username]` was used too.)
- The browser is redirected to `/user/[username]`, and the request is handled by
the single-user notebook server.
The single-user server identifies the user with the Hub via OAuth:
- on request, the single-user server checks a cookie
- if no cookie is set, redirect to the Hub for verification via OAuth
- after verification at the Hub, the browser is redirected back to the
single-user server
- the token is verified and stored in a cookie
- if no user is identified, the browser is redirected back to `/hub/login`
## Default Behavior
By default, the **Proxy** listens on all public interfaces on port 8000.
Thus you can reach JupyterHub through either:
- `http://localhost:8000`
- or any other public IP or domain pointing to your system.
In their default configuration, the other services, the **Hub** and
**Single-User Notebook Servers**, all communicate with each other on localhost
only.
By default, starting JupyterHub will write two files to disk in the current
working directory:
- `jupyterhub.sqlite` is the SQLite database containing all of the state of the
**Hub**. This file allows the **Hub** to remember which users are running and
where, as well as storing other information enabling you to restart parts of
JupyterHub separately. It is important to note that this database contains
**no** sensitive information other than **Hub** usernames.
- `jupyterhub_cookie_secret` is the encryption key used for securing cookies.
This file needs to persist so that a **Hub** server restart will avoid
invalidating cookies. Conversely, deleting this file and restarting the server
effectively invalidates all login cookies. The cookie secret file is discussed
in the [Cookie Secret section of the Security Settings document](../getting-started/security-basics.html).
The location of these files can be specified via configuration settings. It is
recommended that these files be stored in standard UNIX filesystem locations,
such as `/etc/jupyterhub` for all configuration files and `/srv/jupyterhub` for
all security and runtime files.
## Customizing JupyterHub
There are two basic extension points for JupyterHub:
- How users are authenticated by [Authenticators](./authenticators.html)
- How user's single-user notebook server processes are started by
[Spawners](./spawners.html)
Each is governed by a customizable class, and JupyterHub ships with basic
defaults for each.
To enable custom authentication and/or spawning, subclass `Authenticator` or
`Spawner`, and override the relevant methods.

View File

@@ -0,0 +1,106 @@
# Upgrading JupyterHub and its database
From time to time, you may wish to upgrade JupyterHub to take advantage
of new releases. Much of this process is automated using scripts,
such as those generated by alembic for database upgrades. Before upgrading a
JupyterHub deployment, it's critical to backup your data and configurations
before shutting down the JupyterHub process and server.
## Databases: SQLite (default) or RDBMS (PostgreSQL, MySQL)
The default database for JupyterHub is a [SQLite](https://sqlite.org) database.
We have chosen SQLite as JupyterHub's default for its lightweight simplicity
in certain uses such as testing, small deployments and workshops.
When running a long term deployment or a production system, we recommend using
a traditional RDBMS database, such as [PostgreSQL](https://www.postgresql.org)
or [MySQL](https://www.mysql.com), that supports the SQL `ALTER TABLE`
statement.
For production systems, SQLite has some disadvantages when used with JupyterHub:
- `upgrade-db` may not work, and you may need to start with a fresh database
- `downgrade-db` **will not** work if you want to rollback to an earlier
version, so backup the `jupyterhub.sqlite` file before upgrading
The sqlite documentation provides a helpful page about [when to use sqlite and
where traditional RDBMS may be a better choice](https://sqlite.org/whentouse.html).
## The upgrade process
Five fundamental process steps are needed when upgrading JupyterHub and its
database:
1. Backup JupyterHub database
2. Backup JupyterHub configuration file
3. Shutdown the Hub
4. Upgrade JupyterHub
5. Upgrade the database using run `jupyterhub upgrade-db`
Let's take a closer look at each step in the upgrade process as well as some
additional information about JupyterHub databases.
### Backup JupyterHub database
To prevent unintended loss of data or configuration information, you should
back up the JupyterHub database (the default SQLite database or a RDBMS
database using PostgreSQL, MySQL, or others supported by SQLAlchemy):
- If using the default SQLite database, back up the `jupyterhub.sqlite`
database.
- If using an RDBMS database such as PostgreSQL, MySQL, or other supported by
SQLAlchemy, back up the JupyterHub database.
Losing the Hub database is often not a big deal. Information that resides only
in the Hub database includes:
- active login tokens (user cookies, service tokens)
- users added via GitHub UI, instead of config files
- info about running servers
If the following conditions are true, you should be fine clearing the Hub
database and starting over:
- users specified in config file
- user servers are stopped during upgrade
- don't mind causing users to login again after upgrade
### Backup JupyterHub configuration file
Additionally, backing up your configuration file, `jupyterhub_config.py`, to
a secure location.
### Shutdown JupyterHub
Prior to shutting down JupyterHub, you should notify the Hub users of the
scheduled downtime. This gives users the opportunity to finish any outstanding
work in process.
Next, shutdown the JupyterHub service.
### Upgrade JupyterHub
Follow directions that correspond to your package manager, `pip` or `conda`,
for the new JupyterHub release. These directions will guide you to the
specific command. In general, `pip install -U jupyterhub` or
`conda upgrade jupyterhub`
### Upgrade JupyterHub databases
To run the upgrade process for JupyterHub databases, enter:
```
jupyterhub upgrade-db
```
## Upgrade checklist
1. Backup JupyterHub database:
- `jupyterhub.sqlite` when using the default sqlite database
- Your JupyterHub database when using an RDBMS
2. Backup JupyterHub configuration file: `jupyterhub_config.py`
3. Shutdown the Hub
4. Upgrade JupyterHub
- `pip install -U jupyterhub` when using `pip`
- `conda upgrade jupyterhub` when using `conda`
5. Upgrade the database using run `jupyterhub upgrade-db`

View File

@@ -0,0 +1,112 @@
# Security Overview
The **Security Overview** section helps you learn about:
- the design of JupyterHub with respect to web security
- the semi-trusted user
- the available mitigations to protect untrusted users from each other
- the value of periodic security audits.
This overview also helps you obtain a deeper understanding of how JupyterHub
works.
## Semi-trusted and untrusted users
JupyterHub is designed to be a *simple multi-user server for modestly sized
groups* of **semi-trusted** users. While the design reflects serving semi-trusted
users, JupyterHub is not necessarily unsuitable for serving **untrusted** users.
Using JupyterHub with **untrusted** users does mean more work by the
administrator. Much care is required to secure a Hub, with extra caution on
protecting users from each other as the Hub is serving untrusted users.
One aspect of JupyterHub's *design simplicity* for **semi-trusted** users is that
the Hub and single-user servers are placed in a *single domain*, behind a
[*proxy*][configurable-http-proxy]. If the Hub is serving untrusted
users, many of the web's cross-site protections are not applied between
single-user servers and the Hub, or between single-user servers and each
other, since browsers see the whole thing (proxy, Hub, and single user
servers) as a single website (i.e. single domain).
## Protect users from each other
To protect users from each other, a user must **never** be able to write arbitrary
HTML and serve it to another user on the Hub's domain. JupyterHub's
authentication setup prevents a user writing arbitrary HTML and serving it to
another user because only the owner of a given single-user notebook server is
allowed to view user-authored pages served by the given single-user notebook
server.
To protect all users from each other, JupyterHub administrators must
ensure that:
* A user **does not have permission** to modify their single-user notebook server,
including:
- A user **may not** install new packages in the Python environment that runs
their single-user server.
- If the `PATH` is used to resolve the single-user executable (instead of
using an absolute path), a user **may not** create new files in any `PATH`
directory that precedes the directory containing `jupyterhub-singleuser`.
- A user may not modify environment variables (e.g. PATH, PYTHONPATH) for
their single-user server.
* A user **may not** modify the configuration of the notebook server
(the `~/.jupyter` or `JUPYTER_CONFIG_DIR` directory).
If any additional services are run on the same domain as the Hub, the services
**must never** display user-authored HTML that is neither *sanitized* nor *sandboxed*
(e.g. IFramed) to any user that lacks authentication as the author of a file.
## Mitigate security issues
Several approaches to mitigating these issues with configuration
options provided by JupyterHub include:
### Enable subdomains
JupyterHub provides the ability to run single-user servers on their own
subdomains. This means the cross-origin protections between servers has the
desired effect, and user servers and the Hub are protected from each other. A
user's single-user server will be at `username.jupyter.mydomain.com`. This also
requires all user subdomains to point to the same address, which is most easily
accomplished with wildcard DNS. Since this spreads the service across multiple
domains, you will need wildcard SSL, as well. Unfortunately, for many
institutional domains, wildcard DNS and SSL are not available. **If you do plan
to serve untrusted users, enabling subdomains is highly encouraged**, as it
resolves the cross-site issues.
### Disable user config
If subdomains are not available or not desirable, JupyterHub provides a a
configuration option `Spawner.disable_user_config`, which can be set to prevent
the user-owned configuration files from being loaded. After implementing this
option, PATHs and package installation and PATHs are the other things that the
admin must enforce.
### Prevent spawners from evaluating shell configuration files
For most Spawners, `PATH` is not something users can influence, but care should
be taken to ensure that the Spawner does *not* evaluate shell configuration
files prior to launching the server.
### Isolate packages using virtualenv
Package isolation is most easily handled by running the single-user server in
a virtualenv with disabled system-site-packages. The user should not have
permission to install packages into this environment.
It is important to note that the control over the environment only affects the
single-user server, and not the environment(s) in which the user's kernel(s)
may run. Installing additional packages in the kernel environment does not
pose additional risk to the web application's security.
## Security audits
We recommend that you do periodic reviews of your deployment's security. It's
good practice to keep JupyterHub, configurable-http-proxy, and nodejs
versions up to date.
A handy website for testing your deployment is
[Qualsys' SSL analyzer tool](https://www.ssllabs.com/ssltest/analyze.html).
[configurable-http-proxy]: https://github.com/jupyterhub/configurable-http-proxy

View File

@@ -0,0 +1,213 @@
admin
Afterwards
alchemyst
alope
api
API
apps
args
asctime
auth
authenticator
Authenticator
authenticators
Authenticators
Autograde
autograde
autogradeapp
autograded
Autograded
autograder
Autograder
autograding
backends
Bitdiddle
bugfix
Bugfixes
bugtracker
Carreau
Changelog
changelog
checksum
checksums
cmd
cogsci
conda
config
coroutine
coroutines
crt
customizable
datefmt
decrypted
dev
DockerSpawner
dockerspawner
dropdown
duedate
Duedate
ellachao
ellisonbg
entrypoint
env
Filenames
filesystem
formatters
formdata
formgrade
formgrader
gif
GitHub
Gradebook
gradebook
Granger
hardcoded
hOlle
Homebrew
html
http
https
hubapi
Indices
IFramed
inline
iopub
ip
ipynb
IPython
ischurov
ivanslapnicar
jdfreder
jhamrick
jklymak
jonathanmorgan
joschu
JUPYTER
Jupyter
jupyter
jupyterhub
Kerberos
kerberos
letsencrypt
lgpage
linkcheck
linux
localhost
logfile
login
logins
logout
lookup
lphk
mandli
Marr
mathjax
matplotlib
metadata
mikebolt
minrk
Mitigations
mixin
Mixin
multi
multiuser
namespace
nbconvert
nbgrader
neuroscience
nginx
np
npm
oauth
OAuth
oauthenticator
ok
olgabot
osx
PAM
phantomjs
Phantomjs
plugin
plugins
Popen
positionally
postgres
pregenerated
prepend
prepopulate
preprocessor
Preprocessor
prev
Programmatically
programmatically
ps
py
Qualys
quickstart
readonly
redSlug
reinstall
resize
rst
runtime
rw
sandboxed
sansary
singleuser
smeylan
spawner
Spawner
spawners
Spawners
spellcheck
SQL
sqlite
startup
statsd
stdin
stdout
stoppped
subclasses
subcommand
subdomain
subdomains
Subdomains
suchow
suprocesses
svurens
sys
SystemUserSpawner
systemwide
tasilb
teardown
threadsafe
timestamp
timestamps
TLD
todo
toolbar
traitlets
travis
tuples
undeletable
unicode
uninstall
UNIX
unix
untracked
untrusted
url
username
usernames
utcnow
utils
vinaykola
virtualenv
whitelist
whitespace
wildcard
Wildcards
willingc
wordlist
Workflow
workflow

View File

@@ -0,0 +1,327 @@
# Troubleshooting
When troubleshooting, you may see unexpected behaviors or receive an error
message. This section provide links for identifying the cause of the
problem and how to resolve it.
[*Behavior*](#behavior)
- JupyterHub proxy fails to start
- sudospawner fails to run
- What is the default behavior when none of the lists (admin, whitelist,
group whitelist) are set?
[*Errors*](#errors)
- 500 error after spawning my single-user server
[*How do I...?*](#how-do-i)
- Use a chained SSL certificate
- Install JupyterHub without a network connection
- I want access to the whole filesystem, but still default users to their home directory
- How do I increase the number of pySpark executors on YARN?
- How do I use JupyterLab's prerelease version with JupyterHub?
- How do I set up JupyterHub for a workshop (when users are not known ahead of time)?
- How do I set up rotating daily logs?
- Toree integration with HDFS rack awareness script
- Where do I find Docker images and Dockerfiles related to JupyterHub?
[*Troubleshooting commands*](#troubleshooting-commands)
## Behavior
### JupyterHub proxy fails to start
If you have tried to start the JupyterHub proxy and it fails to start:
- check if the JupyterHub IP configuration setting is
``c.JupyterHub.ip = '*'``; if it is, try ``c.JupyterHub.ip = ''``
- Try starting with ``jupyterhub --ip=0.0.0.0``
**Note**: If this occurs on Ubuntu/Debian, check that the you are using a
recent version of node. Some versions of Ubuntu/Debian come with a version
of node that is very old, and it is necessary to update node.
### sudospawner fails to run
If the sudospawner script is not found in the path, sudospawner will not run.
To avoid this, specify sudospawner's absolute path. For example, start
jupyterhub with:
jupyterhub --SudoSpawner.sudospawner_path='/absolute/path/to/sudospawner'
or add:
c.SudoSpawner.sudospawner_path = '/absolute/path/to/sudospawner'
to the config file, `jupyterhub_config.py`.
### What is the default behavior when none of the lists (admin, whitelist, group whitelist) are set?
When nothing is given for these lists, there will be no admins, and all users
who can authenticate on the system (i.e. all the unix users on the server with
a password) will be allowed to start a server. The whitelist lets you limit
this to a particular set of users, and the admin_users lets you specify who
among them may use the admin interface (not necessary, unless you need to do
things like inspect other users' servers, or modify the userlist at runtime).
## Errors
### 500 error after spawning my single-user server
You receive a 500 error when accessing the URL `/user/<your_name>/...`.
This is often seen when your single-user server cannot verify your user cookie
with the Hub.
There are two likely reasons for this:
1. The single-user server cannot connect to the Hub's API (networking
configuration problems)
2. The single-user server cannot *authenticate* its requests (invalid token)
#### Symptoms
The main symptom is a failure to load *any* page served by the single-user
server, met with a 500 error. This is typically the first page at `/user/<your_name>`
after logging in or clicking "Start my server". When a single-user notebook server
receives a request, the notebook server makes an API request to the Hub to
check if the cookie corresponds to the right user. This request is logged.
If everything is working, the response logged will be similar to this:
```
200 GET /hub/api/authorizations/cookie/jupyter-hub-token-name/[secret] (@10.0.1.4) 6.10ms
```
You should see a similar 200 message, as above, in the Hub log when you first
visit your single-user notebook server. If you don't see this message in the log, it
may mean that your single-user notebook server isn't connecting to your Hub.
If you see 403 (forbidden) like this, it's a token problem:
```
403 GET /hub/api/authorizations/cookie/jupyter-hub-token-name/[secret] (@10.0.1.4) 4.14ms
```
Check the logs of the single-user notebook server, which may have more detailed
information on the cause.
#### Causes and resolutions
##### No authorization request
If you make an API request and it is not received by the server, you likely
have a network configuration issue. Often, this happens when the Hub is only
listening on 127.0.0.1 (default) and the single-user servers are not on the
same 'machine' (can be physically remote, or in a docker container or VM). The
fix for this case is to make sure that `c.JupyterHub.hub_ip` is an address
that all single-user servers can connect to, e.g.:
```python
c.JupyterHub.hub_ip = '10.0.0.1'
```
##### 403 GET /hub/api/authorizations/cookie
If you receive a 403 error, the API token for the single-user server is likely
invalid. Commonly, the 403 error is caused by resetting the JupyterHub
database (either removing jupyterhub.sqlite or some other action) while
leaving single-user servers running. This happens most frequently when using
DockerSpawner, because Docker's default behavior is to stop/start containers
which resets the JupyterHub database, rather than destroying and recreating
the container every time. This means that the same API token is used by the
server for its whole life, until the container is rebuilt.
The fix for this Docker case is to remove any Docker containers seeing this
issue (typically all containers created before a certain point in time):
docker rm -f jupyter-name
After this, when you start your server via JupyterHub, it will build a
new container. If this was the underlying cause of the issue, you should see
your server again.
## How do I...?
### Use a chained SSL certificate
Some certificate providers, i.e. Entrust, may provide you with a chained
certificate that contains multiple files. If you are using a chained
certificate you will need to concatenate the individual files by appending the
chain cert and root cert to your host cert:
cat your_host.crt chain.crt root.crt > your_host-chained.crt
You would then set in your `jupyterhub_config.py` file the `ssl_key` and
`ssl_cert` as follows:
c.JupyterHub.ssl_cert = your_host-chained.crt
c.JupyterHub.ssl_key = your_host.key
#### Example
Your certificate provider gives you the following files: `example_host.crt`,
`Entrust_L1Kroot.txt` and `Entrust_Root.txt`.
Concatenate the files appending the chain cert and root cert to your host cert:
cat example_host.crt Entrust_L1Kroot.txt Entrust_Root.txt > example_host-chained.crt
You would then use the `example_host-chained.crt` as the value for
JupyterHub's `ssl_cert`. You may pass this value as a command line option
when starting JupyterHub or more conveniently set the `ssl_cert` variable in
JupyterHub's configuration file, `jupyterhub_config.py`. In `jupyterhub_config.py`,
set:
c.JupyterHub.ssl_cert = /path/to/example_host-chained.crt
c.JupyterHub.ssl_key = /path/to/example_host.key
where `ssl_cert` is example-chained.crt and ssl_key to your private key.
Then restart JupyterHub.
See also [JupyterHub SSL encryption](getting-started.md#ssl-encryption).
### Install JupyterHub without a network connection
Both conda and pip can be used without a network connection. You can make your
own repository (directory) of conda packages and/or wheels, and then install
from there instead of the internet.
For instance, you can install JupyterHub with pip and configurable-http-proxy
with npmbox:
pip wheel jupyterhub
npmbox configurable-http-proxy
### I want access to the whole filesystem, but still default users to their home directory
Setting the following in `jupyterhub_config.py` will configure access to
the entire filesystem and set the default to the user's home directory.
c.Spawner.notebook_dir = '/'
c.Spawner.default_url = '/home/%U' # %U will be replaced with the username
### How do I increase the number of pySpark executors on YARN?
From the command line, pySpark executors can be configured using a command
similar to this one:
pyspark --total-executor-cores 2 --executor-memory 1G
[Cloudera documentation for configuring spark on YARN applications](https://www.cloudera.com/documentation/enterprise/latest/topics/cdh_ig_running_spark_on_yarn.html#spark_on_yarn_config_apps)
provides additional information. The [pySpark configuration documentation](https://spark.apache.org/docs/0.9.0/configuration.html)
is also helpful for programmatic configuration examples.
### How do I use JupyterLab's prerelease version with JupyterHub?
While JupyterLab is still under active development, we have had users
ask about how to try out JupyterLab with JupyterHub.
You need to install and enable the JupyterLab extension system-wide,
then you can change the default URL to `/lab`.
For instance:
pip install jupyterlab
jupyter serverextension enable --py jupyterlab --sys-prefix
The important thing is that jupyterlab is installed and enabled in the
single-user notebook server environment. For system users, this means
system-wide, as indicated above. For Docker containers, it means inside
the single-user docker image, etc.
In `jupyterhub_config.py`, configure the Spawner to tell the single-user
notebook servers to default to JupyterLab:
c.Spawner.default_url = '/lab'
### How do I set up JupyterHub for a workshop (when users are not known ahead of time)?
1. Set up JupyterHub using OAuthenticator for GitHub authentication
2. Configure whitelist to be an empty list in` jupyterhub_config.py`
3. Configure admin list to have workshop leaders be listed with administrator privileges.
Users will need a GitHub account to login and be authenticated by the Hub.
### How do I set up rotating daily logs?
You can do this with [logrotate](https://linux.die.net/man/8/logrotate),
or pipe to `logger` to use syslog instead of directly to a file.
For example, with this logrotate config file:
```
/var/log/jupyterhub.log {
copytruncate
daily
}
```
and run this daily by putting a script in `/etc/cron.daily/`:
```bash
logrotate /path/to/above-config
```
Or use syslog:
jupyterhub | logger -t jupyterhub
## Troubleshooting commands
The following commands provide additional detail about installed packages,
versions, and system information that may be helpful when troubleshooting
a JupyterHub deployment. The commands are:
- System and deployment information
```bash
jupyter troubleshooting
```
- Kernel information
```bash
jupyter kernelspec list
```
- Debug logs when running JupyterHub
```bash
jupyterhub --debug
```
### Toree integration with HDFS rack awareness script
The Apache Toree kernel will an issue, when running with JupyterHub, if the standard HDFS
rack awareness script is used. This will materialize in the logs as a repeated WARN:
```bash
16/11/29 16:24:20 WARN ScriptBasedMapping: Exception running /etc/hadoop/conf/topology_script.py some.ip.address
ExitCodeException exitCode=1: File "/etc/hadoop/conf/topology_script.py", line 63
print rack
^
SyntaxError: Missing parentheses in call to 'print'
at `org.apache.hadoop.util.Shell.runCommand(Shell.java:576)`
```
In order to resolve this issue, there are two potential options.
1. Update HDFS core-site.xml, so the parameter "net.topology.script.file.name" points to a custom
script (e.g. /etc/hadoop/conf/custom_topology_script.py). Copy the original script and change the first line point
to a python two installation (e.g. /usr/bin/python).
2. In spark-env.sh add a Python 2 installation to your path (e.g. export PATH=/opt/anaconda2/bin:$PATH).
### Where do I find Docker images and Dockerfiles related to JupyterHub?
Docker images can be found at the [JupyterHub organization on DockerHub](https://hub.docker.com/u/jupyterhub/).
The Docker image [jupyterhub/singleuser](https://hub.docker.com/r/jupyterhub/singleuser/)
provides an example single user notebook server for use with DockerSpawner.
Additional single user notebook server images can be found at the [Jupyter
organization on DockerHub](https://hub.docker.com/r/jupyter/) and information
about each image at the [jupyter/docker-stacks repo](https://github.com/jupyter/docker-stacks).

View File

@@ -0,0 +1,14 @@
Tutorials
=========
This section provides links to documentation that helps a user do a specific
task.
* :doc:`upgrade-dot-eight`
* `Zero to JupyterHub with Kubernetes <https://zero-to-jupyterhub.readthedocs.io/en/latest/>`_
.. toctree::
:maxdepth: 1
:hidden:
upgrade-dot-eight

View File

@@ -0,0 +1,93 @@
.. upgrade-dot-eight:
Upgrading to JupyterHub version 0.8
===================================
This document will assist you in upgrading an existing JupyterHub deployment
from version 0.7 to version 0.8.
Upgrade checklist
-----------------
0. Review the release notes. Review any deprecated features and pay attention
to any backwards incompatible changes
1. Backup JupyterHub database:
- ``jupyterhub.sqlite`` when using the default sqlite database
- Your JupyterHub database when using an RDBMS
2. Backup the existing JupyterHub configuration file: ``jupyterhub_config.py``
3. Shutdown the Hub
4. Upgrade JupyterHub
- ``pip install -U jupyterhub`` when using ``pip``
- ``conda upgrade jupyterhub`` when using ``conda``
5. Upgrade the database using run ```jupyterhub upgrade-db``
6. Update the JupyterHub configuration file ``jupyterhub_config.py``
Backup JupyterHub database
--------------------------
To prevent unintended loss of data or configuration information, you should
back up the JupyterHub database (the default SQLite database or a RDBMS
database using PostgreSQL, MySQL, or others supported by SQLAlchemy):
- If using the default SQLite database, back up the ``jupyterhub.sqlite``
database.
- If using an RDBMS database such as PostgreSQL, MySQL, or other supported by
SQLAlchemy, back up the JupyterHub database.
.. note::
Losing the Hub database is often not a big deal. Information that resides only
in the Hub database includes:
- active login tokens (user cookies, service tokens)
- users added via GitHub UI, instead of config files
- info about running servers
If the following conditions are true, you should be fine clearing the Hub
database and starting over:
- users specified in config file
- user servers are stopped during upgrade
- don't mind causing users to login again after upgrade
Backup JupyterHub configuration file
------------------------------------
Backup up your configuration file, ``jupyterhub_config.py``, to a secure
location.
Shutdown JupyterHub
-------------------
- Prior to shutting down JupyterHub, you should notify the Hub users of the
scheduled downtime.
- Shutdown the JupyterHub service.
Upgrade JupyterHub
------------------
Follow directions that correspond to your package manager, ``pip`` or ``conda``,
for the new JupyterHub release:
- ``pip install -U jupyterhub`` for ``pip``
- ``conda upgrade jupyterhub`` for ``conda``
Upgrade the proxy, authenticator, or spawner if needed.
Upgrade JupyterHub database
---------------------------
To run the upgrade process for JupyterHub databases, enter::
jupyterhub upgrade-db
Update the JupyterHub configuration file
----------------------------------------
Create a new JupyterHub configuration file or edit a copy of the existing
file ``jupyterhub_config.py``.
Start JupyterHub
----------------
Start JupyterHub with the same command that you used before the upgrade.

View File

@@ -1,89 +0,0 @@
# Writing a custom Spawner
Each single-user server is started by a [Spawner][].
The Spawner represents an abstract interface to a process,
and a custom Spawner needs to be able to take three actions:
1. start the process
2. poll whether the process is still running
3. stop the process
See a list of custom Spawners [on the wiki](https://github.com/jupyter/jupyterhub/wiki/Spawners).
## Spawner.start
`Spawner.start` should start the single-user server for a single user.
Information about the user can be retrieved from `self.user`,
an object encapsulating the user's name, authentication, and server info.
When `Spawner.start` returns, it should have stored the IP and port
of the single-user server in `self.user.server`.
**NOTE:** when writing coroutines, *never* `yield` in between a db change and a commit.
Most `Spawner.start`s should have something looking like:
```python
def start(self):
self.user.server.ip = 'localhost' # or other host or IP address, as seen by the Hub
self.user.server.port = 1234 # port selected somehow
self.db.commit() # always commit before yield, if modifying db values
yield self._actually_start_server_somehow()
```
When `Spawner.start` returns, the single-user server process should actually be running,
not just requested. JupyterHub can handle `Spawner.start` being very slow
(such as PBS-style batch queues, or instantiating whole AWS instances)
via relaxing the `Spawner.start_timeout` config value.
## Spawner.poll
`Spawner.poll` should check if the spawner is still running.
It should return `None` if it is still running,
and an integer exit status, otherwise.
For the local process case, this uses `os.kill(PID, 0)`
to check if the process is still around.
## Spawner.stop
`Spawner.stop` should stop the process. It must be a tornado coroutine,
and should return when the process has finished exiting.
## Spawner state
JupyterHub should be able to stop and restart without having to teardown
single-user servers. This means that a Spawner may need to persist
some information that it can be restored.
A dictionary of JSON-able state can be used to store this information.
Unlike start/stop/poll, the state methods must not be coroutines.
In the single-process case, this is only the process ID of the server:
```python
def get_state(self):
"""get the current state"""
state = super().get_state()
if self.pid:
state['pid'] = self.pid
return state
def load_state(self, state):
"""load state from the database"""
super().load_state(state)
if 'pid' in state:
self.pid = state['pid']
def clear_state(self):
"""clear any state (called after shutdown)"""
super().clear_state()
self.pid = 0
```
[Spawner]: ../jupyterhub/spawner.py

View File

@@ -0,0 +1,54 @@
"""autodoc extension for configurable traits"""
from traitlets import TraitType, Undefined
from sphinx.domains.python import PyClassmember
from sphinx.ext.autodoc import ClassDocumenter, AttributeDocumenter
class ConfigurableDocumenter(ClassDocumenter):
"""Specialized Documenter subclass for traits with config=True"""
objtype = 'configurable'
directivetype = 'class'
def get_object_members(self, want_all):
"""Add traits with .tag(config=True) to members list"""
check, members = super().get_object_members(want_all)
get_traits = self.object.class_own_traits if self.options.inherited_members \
else self.object.class_traits
trait_members = []
for name, trait in sorted(get_traits(config=True).items()):
# put help in __doc__ where autodoc will look for it
trait.__doc__ = trait.help
trait_members.append((name, trait))
return check, trait_members + members
class TraitDocumenter(AttributeDocumenter):
objtype = 'trait'
directivetype = 'attribute'
member_order = 1
priority = 100
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
return isinstance(member, TraitType)
def format_name(self):
return 'config c.' + super().format_name()
def add_directive_header(self, sig):
default = self.object.get_default_value()
if default is Undefined:
default_s = ''
else:
default_s = repr(default)
sig = ' = {}({})'.format(
self.object.__class__.__name__,
default_s,
)
return super().add_directive_header(sig)
def setup(app):
app.add_autodocumenter(ConfigurableDocumenter)
app.add_autodocumenter(TraitDocumenter)

View File

@@ -0,0 +1,130 @@
# Bootstrapping your users
Before spawning a notebook to the user, it could be useful to
do some preparation work in a bootstrapping process.
Common use cases are:
*Providing writeable storage for LDAP users*
Your Jupyterhub is configured to use the LDAPAuthenticator and DockerSpawer.
* The user has no file directory on the host since your are using LDAP.
* When a user has no directory and DockerSpawner wants to mount a volume,
the spawner will use docker to create a directory.
Since the docker daemon is running as root, the generated directory for the volume
mount will not be writeable by the `jovyan` user inside of the container.
For the directory to be useful to the user, the permissions on the directory
need to be modified for the user to have write access.
*Prepopulating Content*
Another use would be to copy initial content, such as tutorial files or reference
material, into the user's space when a notebook server is newly spawned.
You can define your own bootstrap process by implementing a `pre_spawn_hook` on any spawner.
The Spawner itself is passed as parameter to your hook and you can easily get the contextual information out of the spawning process.
If you implement a hook, make sure that it is *idempotent*. It will be executed every time
a notebook server is spawned to the user. That means you should somehow
ensure that things which should run only once are not running again and again.
For example, before you create a directory, check if it exists.
Bootstrapping examples:
### Example #1 - Create a user directory
Create a directory for the user, if none exists
```python
# in jupyterhub_config.py
import os
def create_dir_hook(spawner):
username = spawner.user.name # get the username
volume_path = os.path.join('/volumes/jupyterhub', username)
if not os.path.exists(volume_path):
# create a directory with umask 0755
# hub and container user must have the same UID to be writeable
# still readable by other users on the system
os.mkdir(volume_path, 0o755)
# now do whatever you think your user needs
# ...
pass
# attach the hook function to the spawner
c.Spawner.pre_spawn_hook = create_dir_hook
```
### Example #2 - Run a shell script
You can specify a plain ole' shell script (or any other executable) to be run
by the bootstrap process.
For example, you can execute a shell script and as first parameter pass the name
of the user:
```python
# in jupyterhub_config.py
from subprocess import check_call
import os
def my_script_hook(spawner):
username = spawner.user.name # get the username
script = os.path.join(os.path.dirname(__file__), 'bootstrap.sh')
check_call([script, username])
# attach the hook function to the spawner
c.Spawner.pre_spawn_hook = my_script_hook
```
Here's an example on what you could do in your shell script. See also
`/examples/bootstrap-script/`
```bash
#!/bin/bash
# Bootstrap example script
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
# - The first parameter for the Bootstrap Script is the USER.
USER=$1
if ["$USER" == ""]; then
exit 1
fi
# ----------------------------------------------------------------------------
# This example script will do the following:
# - create one directory for the user $USER in a BASE_DIRECTORY (see below)
# - create a "tutorials" directory within and download and unzip
# the PythonDataScienceHandbook from GitHub
# Start the Bootstrap Process
echo "bootstrap process running for user $USER ..."
# Base Directory: All Directories for the user will be below this point
BASE_DIRECTORY=/volumes/jupyterhub/
# User Directory: That's the private directory for the user to be created, if none exists
USER_DIRECTORY=$BASE_DIRECTORY/$USER
if [ -d "$USER_DIRECTORY" ]; then
echo "...directory for user already exists. skipped"
exit 0 # all good. nothing to do.
else
echo "...creating a directory for the user: $USER_DIRECTORY"
mkdir $USER_DIRECTORY
echo "...initial content loading for user ..."
mkdir $USER_DIRECTORY/tutorials
cd $USER_DIRECTORY/tutorials
wget https://github.com/jakevdp/PythonDataScienceHandbook/archive/master.zip
unzip -o master.zip
rm master.zip
fi
exit 0
```

View File

@@ -0,0 +1,48 @@
#!/bin/bash
# Bootstrap example script
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
# - The first parameter for the Bootstrap Script is the USER.
USER=$1
if ["$USER" == ""]; then
exit 1
fi
# ----------------------------------------------------------------------------
# This example script will do the following:
# - create one directory for the user $USER in a BASE_DIRECTORY (see below)
# - create a "tutorials" directory within and download and unzip the PythonDataScienceHandbook from GitHub
# Start the Bootstrap Process
echo "bootstrap process running for user $USER ..."
# Base Directory: All Directories for the user will be below this point
BASE_DIRECTORY=/volumes/jupyterhub
# User Directory: That's the private directory for the user to be created, if none exists
USER_DIRECTORY=$BASE_DIRECTORY/$USER
if [ -d "$USER_DIRECTORY" ]; then
echo "...directory for user already exists. skipped"
exit 0 # all good. nothing to do.
else
echo "...creating a directory for the user: $USER_DIRECTORY"
mkdir $USER_DIRECTORY
# mkdir did not succeed?
if [ $? -ne 0 ] ; then
exit 1
fi
echo "...initial content loading for user ..."
mkdir $USER_DIRECTORY/tutorials
cd $USER_DIRECTORY/tutorials
wget https://github.com/jakevdp/PythonDataScienceHandbook/archive/master.zip
unzip -o master.zip
rm master.zip
fi
exit 0

View File

@@ -0,0 +1,26 @@
# Example for a Spawner.pre_spawn_hook
# create a directory for the user before the spawner starts
import os
def create_dir_hook(spawner):
username = spawner.user.name # get the username
volume_path = os.path.join('/volumes/jupyterhub', username)
if not os.path.exists(volume_path):
os.mkdir(volume_path, 0o755)
# now do whatever you think your user needs
# ...
# attach the hook function to the spawner
c.Spawner.pre_spawn_hook = create_dir_hook
# Use the DockerSpawner to serve your users' notebooks
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
from jupyter_client.localinterfaces import public_ips
c.JupyterHub.hub_ip = public_ips()[0]
c.DockerSpawner.hub_ip_connect = public_ips()[0]
c.DockerSpawner.container_ip = "0.0.0.0"
# You can now mount the volume to the docker container as we've
# made sure the directory exists
c.DockerSpawner.volumes = { '/volumes/jupyterhub/{username}/': '/home/jovyan/work' }

View File

@@ -0,0 +1,41 @@
# `cull-idle` Example
The `cull_idle_servers.py` file provides a script to cull and shut down idle
single-user notebook servers. This script is used when `cull-idle` is run as
a Service or when it is run manually as a standalone script.
## Configure `cull-idle` to run as a Hub-Managed Service
In `jupyterhub_config.py`, add the following dictionary for the `cull-idle`
Service to the `c.JupyterHub.services` list:
```python
c.JupyterHub.services = [
{
'name': 'cull-idle',
'admin': True,
'command': 'python cull_idle_servers.py --timeout=3600'.split(),
}
]
```
where:
- `'admin': True` indicates that the Service has 'admin' permissions, and
- `'command'` indicates that the Service will be managed by the Hub.
## Run `cull-idle` manually as a standalone script
This will run `cull-idle` manually. `cull-idle` can be run as a standalone
script anywhere with access to the Hub, and will periodically check for idle
servers and shut them down via the Hub's REST API. In order to shutdown the
servers, the token given to cull-idle must have admin privileges.
Generate an API token and store it in the `JUPYTERHUB_API_TOKEN` environment
variable. Run `cull_idle_servers.py` manually.
```bash
export JUPYTERHUB_API_TOKEN=`jupyterhub token`
python cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
```

View File

@@ -9,10 +9,21 @@ so cull timeout should be greater than the sum of:
- single-user websocket ping interval (default: 30s)
- JupyterHub.last_activity_interval (default: 5 minutes)
Generate an API token and store it in `JPY_API_TOKEN`:
You can run this as a service managed by JupyterHub with this in your config::
export JPY_API_TOKEN=`jupyterhub token`
python cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub]
c.JupyterHub.services = [
{
'name': 'cull-idle',
'admin': True,
'command': 'python cull_idle_servers.py --timeout=3600'.split(),
}
]
Or run it manually by generating an API token and storing it in `JUPYTERHUB_API_TOKEN`:
export JUPYTERHUB_API_TOKEN=`jupyterhub token`
python cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]
"""
import datetime
@@ -29,12 +40,15 @@ from tornado.options import define, options, parse_command_line
@coroutine
def cull_idle(url, api_token, timeout):
"""cull idle single-user servers"""
def cull_idle(url, api_token, timeout, cull_users=False):
"""Shutdown idle single-user servers
If cull_users, inactive *users* will be deleted as well.
"""
auth_header = {
'Authorization': 'token %s' % api_token
}
req = HTTPRequest(url=url + '/api/users',
req = HTTPRequest(url=url + '/users',
headers=auth_header,
)
now = datetime.datetime.utcnow()
@@ -43,35 +57,59 @@ def cull_idle(url, api_token, timeout):
resp = yield client.fetch(req)
users = json.loads(resp.body.decode('utf8', 'replace'))
futures = []
for user in users:
last_activity = parse_date(user['last_activity'])
if user['server'] and last_activity < cull_limit:
app_log.info("Culling %s (inactive since %s)", user['name'], last_activity)
req = HTTPRequest(url=url + '/api/users/%s/server' % user['name'],
@coroutine
def cull_one(user, last_activity):
"""cull one user"""
# shutdown server first. Hub doesn't allow deleting users with running servers.
if user['server']:
app_log.info("Culling server for %s (inactive since %s)", user['name'], last_activity)
req = HTTPRequest(url=url + '/users/%s/server' % user['name'],
method='DELETE',
headers=auth_header,
)
futures.append((user['name'], client.fetch(req)))
elif user['server'] and last_activity > cull_limit:
yield client.fetch(req)
if cull_users:
app_log.info("Culling user %s (inactive since %s)", user['name'], last_activity)
req = HTTPRequest(url=url + '/users/%s' % user['name'],
method='DELETE',
headers=auth_header,
)
yield client.fetch(req)
for user in users:
if not user['server'] and not cull_users:
# server not running and not culling users, nothing to do
continue
last_activity = parse_date(user['last_activity'])
if last_activity < cull_limit:
futures.append((user['name'], cull_one(user, last_activity)))
else:
app_log.debug("Not culling %s (active since %s)", user['name'], last_activity)
for (name, f) in futures:
yield f
app_log.debug("Finished culling %s", name)
if __name__ == '__main__':
define('url', default='http://127.0.0.1:8081/hub', help="The JupyterHub API URL")
define('url', default=os.environ.get('JUPYTERHUB_API_URL'), help="The JupyterHub API URL")
define('timeout', default=600, help="The idle timeout (in seconds)")
define('cull_every', default=0, help="The interval (in seconds) for checking for idle servers to cull")
define('cull_users', default=False,
help="""Cull users in addition to servers.
This is for use in temporary-user cases such as tmpnb.""",
)
parse_command_line()
if not options.cull_every:
options.cull_every = options.timeout // 2
api_token = os.environ['JPY_API_TOKEN']
api_token = os.environ['JUPYTERHUB_API_TOKEN']
loop = IOLoop.current()
cull = lambda : cull_idle(options.url, api_token, options.timeout)
cull = lambda : cull_idle(options.url, api_token, options.timeout, options.cull_users)
# run once before scheduling periodic call
loop.run_sync(cull)
# schedule periodic cull

View File

@@ -0,0 +1,8 @@
# run cull-idle as a service
c.JupyterHub.services = [
{
'name': 'cull-idle',
'admin': True,
'command': 'python cull_idle_servers.py --timeout=3600'.split(),
}
]

View File

@@ -1,4 +1,4 @@
FROM jupyter/jupyterhub
FROM jupyter/jupyterhub-onbuild
MAINTAINER Jupyter Project <jupyter@googlegroups.com>

View File

@@ -0,0 +1,25 @@
# Running a shared notebook as a service
This directory contains two examples of running a shared notebook server as a service,
one as a 'managed' service, and one as an external service with supervisor.
These examples require jupyterhub >= 0.7.2.
A single-user notebook server is run as a service,
and uses groups to authenticate a collection of users with the Hub.
In these examples, a JupyterHub group `'shared'` is created,
and a notebook server is spawned at `/services/shared-notebook`.
Any user in the `'shared'` group will be able to access the notebook server at `/services/shared-notebook/`.
In both examples, you will want to select the name of the group,
and the name of the shared-notebook service.
In the external example, some extra steps are required to set up supervisor:
1. select a system user to run the service. This is a user on the system, and does not need to be a Hub user. Add this to the user field in `shared-notebook.conf`, replacing `someuser`.
2. generate a secret token for authentication, and replace the `super-secret` fields in `shared-notebook-service` and `jupyterhub_config.py`
3. install `shared-notebook-service` somewhere on your system, and update `/path/to/shared-notebook-service` to the absolute path of this destination
3. copy `shared-notebook.conf` to `/etc/supervisor/conf.d/`
4. `supervisorctl reload`

View File

@@ -0,0 +1,24 @@
# our user list
c.Authenticator.whitelist = [
'minrk',
'ellisonbg',
'willingc',
]
# ellisonbg and willingc have access to a shared server:
c.JupyterHub.load_groups = {
'shared': [
'ellisonbg',
'willingc',
]
}
# start the notebook server as a service
c.JupyterHub.services = [
{
'name': 'shared-notebook',
'url': 'http://127.0.0.1:9999',
'api_token': 'super-secret',
}
]

View File

@@ -0,0 +1,9 @@
#!/bin/bash -l
set -e
export JUPYTERHUB_API_TOKEN=super-secret
export JUPYTERHUB_SERVICE_URL=http://127.0.0.1:9999
export JUPYTERHUB_SERVICE_NAME=shared-notebook
jupyterhub-singleuser \
--group='shared'

View File

@@ -0,0 +1,14 @@
[program:jupyterhub-shared-notebook]
user=someuser
command=bash -l /path/to/shared-notebook-service
directory=/home/someuser
autostart=true
autorestart=true
startretries=1
exitcodes=0,2
stopsignal=TERM
redirect_stderr=true
stdout_logfile=/var/log/jupyterhub-service-shared-notebook.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stdout_capture_maxbytes=1MB

View File

@@ -0,0 +1,32 @@
# our user list
c.Authenticator.whitelist = [
'minrk',
'ellisonbg',
'willingc',
]
# ellisonbg and willingc have access to a shared server:
c.JupyterHub.load_groups = {
'shared': [
'ellisonbg',
'willingc',
]
}
service_name = 'shared-notebook'
service_port = 9999
group_name = 'shared'
# start the notebook server as a service
c.JupyterHub.services = [
{
'name': service_name,
'url': 'http://127.0.0.1:{}'.format(service_port),
'command': [
'jupyterhub-singleuser',
'--group=shared',
'--debug',
],
}
]

View File

@@ -0,0 +1,33 @@
# Authenticating a flask service with JupyterHub
Uses `jupyterhub.services.HubAuth` to authenticate requests with the Hub in a [flask][] application.
## Run
1. Launch JupyterHub and the `whoami service` with
jupyterhub --ip=127.0.0.1
2. Visit http://127.0.0.1:8000/services/whoami or http://127.0.0.1:8000/services/whoami-oauth
After logging in with your local-system credentials, you should see a JSON dump of your user info:
```json
{
"admin": false,
"last_activity": "2016-05-27T14:05:18.016372",
"name": "queequeg",
"pending": null,
"server": "/user/queequeg"
}
```
This relies on the Hub starting the whoami service, via config (see [jupyterhub_config.py](./jupyterhub_config.py)).
A similar service could be run externally, by setting the JupyterHub service environment variables:
JUPYTERHUB_API_TOKEN
JUPYTERHUB_SERVICE_PREFIX
[flask]: http://flask.pocoo.org

View File

@@ -0,0 +1,21 @@
import os
import sys
c.JupyterHub.services = [
{
'name': 'whoami',
'url': 'http://127.0.0.1:10101',
'command': ['flask', 'run', '--port=10101'],
'environment': {
'FLASK_APP': 'whoami-flask.py',
}
},
{
'name': 'whoami-oauth',
'url': 'http://127.0.0.1:10201',
'command': ['flask', 'run', '--port=10201'],
'environment': {
'FLASK_APP': 'whoami-oauth.py',
}
},
]

View File

@@ -0,0 +1,4 @@
export CONFIGPROXY_AUTH_TOKEN=`openssl rand -hex 32`
# start JupyterHub
jupyterhub --ip=127.0.0.1

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""
whoami service authentication with the Hub
"""
from functools import wraps
import json
import os
from urllib.parse import quote
from flask import Flask, redirect, request, Response
from jupyterhub.services.auth import HubAuth
prefix = os.environ.get('JUPYTERHUB_SERVICE_PREFIX', '/')
auth = HubAuth(
api_token=os.environ['JUPYTERHUB_API_TOKEN'],
cache_max_age=60,
)
app = Flask(__name__)
def authenticated(f):
"""Decorator for authenticating with the Hub"""
@wraps(f)
def decorated(*args, **kwargs):
cookie = request.cookies.get(auth.cookie_name)
token = request.headers.get(auth.auth_header_name)
if cookie:
user = auth.user_for_cookie(cookie)
elif token:
user = auth.user_for_token(token)
else:
user = None
if user:
return f(user, *args, **kwargs)
else:
# redirect to login url on failed auth
return redirect(auth.login_url + '?next=%s' % quote(request.path))
return decorated
@app.route(prefix + '/')
@authenticated
def whoami(user):
return Response(
json.dumps(user, indent=1, sort_keys=True),
mimetype='application/json',
)

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
"""
whoami service authentication with the Hub
"""
from functools import wraps
import json
import os
from flask import Flask, redirect, request, Response, make_response
from jupyterhub.services.auth import HubOAuth
prefix = os.environ.get('JUPYTERHUB_SERVICE_PREFIX', '/')
auth = HubOAuth(
api_token=os.environ['JUPYTERHUB_API_TOKEN'],
cache_max_age=60,
)
app = Flask(__name__)
def authenticated(f):
"""Decorator for authenticating with the Hub via OAuth"""
@wraps(f)
def decorated(*args, **kwargs):
token = request.cookies.get(auth.cookie_name)
if token:
user = auth.user_for_token(token)
else:
user = None
if user:
return f(user, *args, **kwargs)
else:
# redirect to login url on failed auth
state = auth.generate_state(next_url=request.path)
response = make_response(redirect(auth.login_url + '&state=%s' % state))
response.set_cookie(auth.state_cookie_name, state)
return response
return decorated
@app.route(prefix)
@authenticated
def whoami(user):
return Response(
json.dumps(user, indent=1, sort_keys=True),
mimetype='application/json',
)
@app.route(prefix + 'oauth_callback')
def oauth_callback():
code = request.args.get('code', None)
if code is None:
return 403
# validate state field
arg_state = request.args.get('state', None)
cookie_state = request.cookies.get(auth.state_cookie_name)
if arg_state is None or arg_state != cookie_state:
# state doesn't match
return 403
token = auth.token_for_code(code)
next_url = auth.get_next_url(cookie_state) or prefix
response = make_response(redirect(next_url))
response.set_cookie(auth.cookie_name, token)
return response

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -0,0 +1,34 @@
# Authenticating a service with JupyterHub
Uses `jupyterhub.services.HubAuthenticated` to authenticate requests with the Hub.
There is an implementation each of cookie-based `HubAuthenticated` and OAuth-based `HubOAuthenticated`.
## Run
1. Launch JupyterHub and the `whoami service` with
jupyterhub --ip=127.0.0.1
2. Visit http://127.0.0.1:8000/services/whoami or http://127.0.0.1:8000/services/whoami-oauth
After logging in with your local-system credentials, you should see a JSON dump of your user info:
```json
{
"admin": false,
"last_activity": "2016-05-27T14:05:18.016372",
"name": "queequeg",
"pending": null,
"server": "/user/queequeg"
}
```
This relies on the Hub starting the whoami services, via config (see [jupyterhub_config.py](./jupyterhub_config.py)).
A similar service could be run externally, by setting the JupyterHub service environment variables:
JUPYTERHUB_API_TOKEN
JUPYTERHUB_SERVICE_PREFIX
or instantiating and configuring a HubAuth object yourself, and attaching it as `self.hub_auth` in your HubAuthenticated handlers.

View File

@@ -0,0 +1,15 @@
import os
import sys
c.JupyterHub.services = [
{
'name': 'whoami',
'url': 'http://127.0.0.1:10101',
'command': [sys.executable, './whoami.py'],
},
{
'name': 'whoami-oauth',
'url': 'http://127.0.0.1:10102',
'command': [sys.executable, './whoami-oauth.py'],
},
]

View File

@@ -0,0 +1,43 @@
"""An example service authenticating with the Hub.
This example service serves `/services/whoami/`,
authenticated with the Hub,
showing the user their own info.
"""
from getpass import getuser
import json
import os
from urllib.parse import urlparse
from tornado.ioloop import IOLoop
from tornado.httpserver import HTTPServer
from tornado.web import RequestHandler, Application, authenticated
from jupyterhub.services.auth import HubOAuthenticated, HubOAuthCallbackHandler
from jupyterhub.utils import url_path_join
class WhoAmIHandler(HubOAuthenticated, RequestHandler):
hub_users = {getuser()} # the users allowed to access this service
@authenticated
def get(self):
user_model = self.get_current_user()
self.set_header('content-type', 'application/json')
self.write(json.dumps(user_model, indent=1, sort_keys=True))
def main():
app = Application([
(os.environ['JUPYTERHUB_SERVICE_PREFIX'], WhoAmIHandler),
(url_path_join(os.environ['JUPYTERHUB_SERVICE_PREFIX'], 'oauth_callback'), HubOAuthCallbackHandler),
(r'.*', WhoAmIHandler),
], cookie_secret=os.urandom(32))
http_server = HTTPServer(app)
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
http_server.listen(url.port, url.hostname)
IOLoop.current().start()
if __name__ == '__main__':
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -0,0 +1,40 @@
"""An example service authenticating with the Hub.
This serves `/services/whoami/`, authenticated with the Hub, showing the user their own info.
"""
from getpass import getuser
import json
import os
from urllib.parse import urlparse
from tornado.ioloop import IOLoop
from tornado.httpserver import HTTPServer
from tornado.web import RequestHandler, Application, authenticated
from jupyterhub.services.auth import HubAuthenticated
class WhoAmIHandler(HubAuthenticated, RequestHandler):
hub_users = {getuser()} # the users allowed to access me
@authenticated
def get(self):
user_model = self.get_current_user()
self.set_header('content-type', 'application/json')
self.write(json.dumps(user_model, indent=1, sort_keys=True))
def main():
app = Application([
(os.environ['JUPYTERHUB_SERVICE_PREFIX'] + '/?', WhoAmIHandler),
(r'.*', WhoAmIHandler),
])
http_server = HTTPServer(app)
url = urlparse(os.environ['JUPYTERHUB_SERVICE_URL'])
http_server.listen(url.port, url.hostname)
IOLoop.current().start()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,46 @@
"""
Example JupyterHub config allowing users to specify environment variables and notebook-server args
"""
import shlex
from jupyterhub.spawner import LocalProcessSpawner
class DemoFormSpawner(LocalProcessSpawner):
def _options_form_default(self):
default_env = "YOURNAME=%s\n" % self.user.name
return """
<label for="args">Extra notebook CLI arguments</label>
<input name="args" placeholder="e.g. --debug"></input>
<label for="env">Environment variables (one per line)</label>
<textarea name="env">{env}</textarea>
""".format(env=default_env)
def options_from_form(self, formdata):
options = {}
options['env'] = env = {}
env_lines = formdata.get('env', [''])
for line in env_lines[0].splitlines():
if line:
key, value = line.split('=', 1)
env[key.strip()] = value.strip()
arg_s = formdata.get('args', [''])[0].strip()
if arg_s:
options['argv'] = shlex.split(arg_s)
return options
def get_args(self):
"""Return arguments to pass to the notebook server"""
argv = super().get_args()
if self.user_options.get('argv'):
argv.extend(self.user_options['argv'])
return argv
def get_env(self):
env = super().get_env()
if self.user_options.get('env'):
env.update(self.user_options['env'])
return env
c.JupyterHub.spawner_class = DemoFormSpawner

View File

@@ -1,2 +1 @@
from .version import version_info, __version__
from ._version import version_info, __version__

View File

@@ -1,5 +1,6 @@
"""Get the data files for this package."""
def get_data_files():
"""Walk up until we find share/jupyter/hub"""
import sys
@@ -21,4 +22,3 @@ def get_data_files():
# Package managers can just override this with the appropriate constant
DATA_FILES_PATH = get_data_files()

45
jupyterhub/_version.py Normal file
View File

@@ -0,0 +1,45 @@
"""JupyterHub version info"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
version_info = (
0,
8,
0,
)
__version__ = '.'.join(map(str, version_info))
def _check_version(hub_version, singleuser_version, log):
"""Compare Hub and single-user server versions"""
if not hub_version:
log.warning("Hub has no version header, which means it is likely < 0.8. Expected %s", __version__)
return
if not singleuser_version:
log.warning("Single-user server has no version header, which means it is likely < 0.8. Expected %s", __version__)
return
# compare minor X.Y versions
if hub_version != singleuser_version:
from distutils.version import LooseVersion as V
hub_major_minor = V(hub_version).version[:2]
singleuser_major_minor = V(singleuser_version).version[:2]
extra = ""
if singleuser_major_minor == hub_major_minor:
# patch-level mismatch or lower, log difference at debug-level
# because this should be fine
log_method = log.debug
else:
# log warning-level for more significant mismatch, such as 0.8 vs 0.9, etc.
log_method = log.warning
extra = " This could cause failure to authenticate and result in redirect loops!"
log_method(
"jupyterhub version %s != jupyterhub-singleuser version %s." + extra,
hub_version,
singleuser_version,
)
else:
log.debug("jupyterhub and jupyterhub-singleuser both on version %s" % hub_version)

67
jupyterhub/alembic.ini Normal file
View File

@@ -0,0 +1,67 @@
# A generic, single database configuration.
[alembic]
script_location = {alembic_dir}
sqlalchemy.url = {db_url}
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s
# max length of characters to apply to the
# "slug" field
#truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false
# version location specification; this defaults
# to jupyterhub/alembic/versions. When using multiple version
# directories, initial revisions must be specified with --version-path
# version_locations = %(here)s/bar %(here)s/bat jupyterhub/alembic/versions
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
class = jupyterhub.log.CoroutineLogFormatter
format = %(color)s[%(levelname)1.1s %(asctime)s.%(msecs).03d %(name)s %(module)s:%(lineno)d]%(end_color)s %(message)s
datefmt = %Y-%m-%d %H:%M:%S

Some files were not shown because too many files have changed in this diff Show More