Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #100 from yuvipanda/rsession-merge
- Loading branch information
Showing
8 changed files
with
248 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
FROM jupyter/r-notebook | ||
|
||
USER root | ||
|
||
RUN apt-get update && \ | ||
apt-get install -y --no-install-recommends \ | ||
libapparmor1 \ | ||
libedit2 \ | ||
lsb-release \ | ||
psmisc \ | ||
libssl1.0.0 \ | ||
; | ||
|
||
# You can use rsession from rstudio's desktop package as well. | ||
ENV RSTUDIO_PKG=rstudio-server-1.0.136-amd64.deb | ||
|
||
RUN wget -q http://download2.rstudio.org/${RSTUDIO_PKG} | ||
RUN dpkg -i ${RSTUDIO_PKG} | ||
RUN rm ${RSTUDIO_PKG} | ||
|
||
RUN apt-get clean && \ | ||
rm -rf /var/lib/apt/lists/* | ||
|
||
USER $NB_USER | ||
|
||
RUN pip install git+https://github.com/jupyterhub/jupyter-rsession-proxy | ||
|
||
# The desktop package uses /usr/lib/rstudio/bin | ||
ENV PATH="${PATH}:/usr/lib/rstudio-server/bin" | ||
ENV LD_LIBRARY_PATH="/usr/lib/R/lib:/lib:/usr/lib/x86_64-linux-gnu:/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server:/opt/conda/lib/R/lib" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# jupyter-rsession-proxy | ||
|
||
**jupyter-rsession-proxy** provides Jupyter server and notebook extensions to proxy RStudio. | ||
|
||
![Screenshot](screenshot.png) | ||
|
||
If you have a JupyterHub deployment, jupyter-rsession-proxy can take advantage of JupyterHub's existing authenticator and spawner to launch RStudio in users' Jupyter environments. You can also run this from within Jupyter. | ||
Note that [RStudio Server Pro](https://www.rstudio.com/products/rstudio-server-pro/architecture) has more featureful authentication and spawning than the standard version, in the event that you do not want to use Jupyter's. | ||
|
||
## Installation | ||
|
||
### Pre-reqs | ||
|
||
#### Install rstudio | ||
Use conda `conda install rstudio` or [download](https://www.rstudio.com/products/rstudio/download-server/) the corresponding package for your platform | ||
|
||
Note that rstudio server is needed to work with this extension. | ||
|
||
### Install jupyter-rsession-proxy | ||
|
||
Install the library: | ||
``` | ||
pip install jupyter-rsession-proxy | ||
``` | ||
|
||
The Dockerfile contains an example installation on top of [jupyter/r-notebook](https://github.com/jupyter/docker-stacks/tree/master/r-notebook). | ||
|
||
|
||
### Multiuser Considerations | ||
|
||
This extension launches an rstudio server process from the jupyter notebook server. This is fine in JupyterHub deployments where user servers are containerized since other users cannot connect to the rstudio server port. In non-containerized JupyterHub deployments, for example on multiuser systems running LocalSpawner or BatchSpawner, this not secure. Any user may connect to rstudio server and run arbitrary code. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import os | ||
import tempfile | ||
import subprocess | ||
import getpass | ||
import shutil | ||
from textwrap import dedent | ||
|
||
def setup_shiny(): | ||
'''Manage a Shiny instance.''' | ||
|
||
name = 'shiny' | ||
def _get_shiny_cmd(port): | ||
conf = dedent(""" | ||
run_as {user}; | ||
server {{ | ||
listen {port}; | ||
location / {{ | ||
site_dir {site_dir}; | ||
log_dir {site_dir}/logs; | ||
directory_index on; | ||
}} | ||
}} | ||
""").format( | ||
user=getpass.getuser(), | ||
port=str(port), | ||
site_dir=os.getcwd() | ||
) | ||
|
||
f = tempfile.NamedTemporaryFile(mode='w', delete=False) | ||
f.write(conf) | ||
f.close() | ||
return ['shiny-server', f.name] | ||
|
||
return { | ||
'command': _get_shiny_cmd, | ||
'launcher_entry': { | ||
'title': 'Shiny', | ||
'icon_path': os.path.join(os.path.dirname(os.path.abspath(__file__)), 'icons', 'shiny.svg') | ||
} | ||
} | ||
|
||
def setup_rstudio(): | ||
def _get_rsession_env(port): | ||
# Detect various environment variables rsession requires to run | ||
# Via rstudio's src/cpp/core/r_util/REnvironmentPosix.cpp | ||
cmd = ['R', '--slave', '--vanilla', '-e', | ||
'cat(paste(R.home("home"),R.home("share"),R.home("include"),R.home("doc"),getRversion(),sep=":"))'] | ||
|
||
r_output = subprocess.check_output(cmd) | ||
R_HOME, R_SHARE_DIR, R_INCLUDE_DIR, R_DOC_DIR, version = \ | ||
r_output.decode().split(':') | ||
|
||
return { | ||
'R_DOC_DIR': R_DOC_DIR, | ||
'R_HOME': R_HOME, | ||
'R_INCLUDE_DIR': R_INCLUDE_DIR, | ||
'R_SHARE_DIR': R_SHARE_DIR, | ||
'RSTUDIO_DEFAULT_R_VERSION_HOME': R_HOME, | ||
'RSTUDIO_DEFAULT_R_VERSION': version, | ||
} | ||
|
||
def _get_rsession_cmd(port): | ||
# Other paths rsession maybe in | ||
other_paths = [ | ||
# When rstudio-server deb is installed | ||
'/usr/lib/rstudio-server/bin/rsession', | ||
# When just rstudio deb is installed | ||
'/usr/lib/rstudio/bin/rsession', | ||
] | ||
if shutil.which('rsession'): | ||
executable = 'rsession' | ||
else: | ||
for op in other_paths: | ||
if os.path.exists(op): | ||
executable = op | ||
break | ||
else: | ||
raise FileNotFoundError('Can not find rsession in PATH') | ||
|
||
return [ | ||
executable, | ||
'--standalone=1', | ||
'--program-mode=server', | ||
'--log-stderr=1', | ||
'--session-timeout-minutes=0', | ||
'--user-identity=' + getpass.getuser(), | ||
'--www-port=' + str(port) | ||
] | ||
|
||
return { | ||
'command': _get_rsession_cmd, | ||
'environment': _get_rsession_env, | ||
'launcher_entry': { | ||
'title': 'RStudio', | ||
'icon_path': os.path.join(os.path.dirname(os.path.abspath(__file__)), 'icons', 'rstudio.svg') | ||
} | ||
} |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import setuptools | ||
|
||
setuptools.setup( | ||
name="jupyter-rsession-proxy", | ||
version='1.0dev', | ||
url="https://github.com/jupyterhub/jupyter-rsession-proxy", | ||
author="Ryan Lovett & Yuvi Panda", | ||
description="Jupyter extension to proxy RStudio's rsession", | ||
packages=setuptools.find_packages(), | ||
keywords=['Jupyter'], | ||
classifiers=['Framework :: Jupyter'], | ||
install_requires=[ | ||
'jupyter-server-proxy' | ||
], | ||
entry_points={ | ||
'jupyter_serverproxy_servers': [ | ||
'rstudio = jupyter_rsession_proxy:setup_rstudio', | ||
'shiny = jupyter_rsession_proxy:setup_shiny' | ||
] | ||
}, | ||
package_data={ | ||
'jupyter_rsession_proxy': ['icons/*'], | ||
}, | ||
) |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.