На основной вопрос "почему юпитер стоит реализовать server-side" есть один простой ответ: для установки пакетов на windows нужно невероятное количество удачи и терпения. Хотя бы потому что нужно правильно подобрать сраный компилятор, для установки зависимостей не бинарями: пруф (архив, peep)
В этой серии мы будем:
вообще, как адекватно поставить виртуальное окружение описано уже давно https://askubuntu.com/a/244642
когда уже работаешь под venv, то просто можно сделать так
тут будет происходит неведома херня: запускаю в виртуальном окружении jupyter notebook, мне в ответ прилетает
`jupyter -h` - Show help information, including available subcommands.
`jupyter --config-dir` - There you can find your {application} cofigs when run `jupyter {application} --generate-config`
`jupyter --paths` - All dirs in one commands
`jupyter --paths --json` -- json like output
`jupyter console -h` - configuration options
`jupyter kernelspec list` - list of available kernels
Такие грабли происходили, потому что сразу надо было прочитать про его console, делаем следующее
а теперь подправим конфиг `vim ~/.jupyter/jupyter_notebook_config.py` вот так:
и можно уже ходить в приложение используя проброс портов по ssh. Это вполне рабочий вариант, но как то коряво.
Это один из тех немногих способов сделать все не по уебански. Даже мульти-юзерность будет.
Вариантов реализации мульти-юзер доступа много, но самый адекватный вариант - придется пакеты ставить глобально
добавим группу для пользаков. Если что, они уже были в системе
возможно надо будет вылогиниться. Через `sudo visudo` добавляем возможность запуска
а потом проверяем командой `sudo -u rhea sudo -n -u $USER /usr/local/bin/sudospawner --help`
Теперь добавляем PAM авторизацию
сначала делаем его окружение
проверяем командой `sudo -u rhea jupyterhub --JupyterHub.spawner_class=sudospawner.SudoSpawner`
Если все нормас, то потом генерим конфиг, что бы не заниматься херней в консоли
открываем лог `tail -f /var/log/jupyterhub/hub.log` в одной консоли
и проверяем командой `sudo -u rhea jupyterhub` в другой
и заходим по адресу http://buben.lan:6535/jupyter/
Вообще я обычно демонизирую женщин, но тут я намерен проделать это с приложкой (с). По мотивам /jupyterhub/wiki
делаем `sudo vim /etc/systemd/system/jupyterhub.service`
потом докинем библиотеки в системные файлы
далее подгружаем новый конфиг с сервисы и магия должна заработать
характерным признаком должно быть, что последняя команда показывает активный процесс
в афтербут сервис добавляется командой `sudo systemctl enable jupyterhub.service`
web-app
у нас есть приготовленный nginx с https терминированием. Только благодаря этому не надо городить кучу конфигов на виртуалке и мудохаться с перевыпуском сертификата за натом. И если мы хотим иметь веб приложение jupyter по адресу `https://box.now.io/jupyter/`, то надо добавить в конфиг такой локэйшн
Есть пара интересных рекомендаций, как можно сделать еще, у этого улыбчивого парня
http://nathan.vertile.com/blog/2017/12/07/run-jupyter-notebook-behind-a-nginx-reverse-proxy-subpath/
но я забил, работает и ладно.
лайфхак для ленивых `sed -i 's/\r$//' nginx.conf`
и рестартануть веб-сервер `/etc/init.d/nginx reload`
Поставить довольно просто для postgre довольно просто
Далее надо настроить тестового пользователя
теперь пробуем подключиться в консоли из под своего робота `sudo -u bender psql`
теперь пробуем из под jupyterhub в ноутбуке используя psycopg пробуем
В этой серии мы будем:
- ставить Jupyter
- сделаем ему мультилеер, сингл-преер - не круто
- сделем из него сервис с автозапуском
- научим его ходить в базу
- научим его ходить а рабочую базу по vpn (уже настроено, хост только прописать надо)
Установка
вообще, как адекватно поставить виртуальное окружение описано уже давно https://askubuntu.com/a/244642
когда уже работаешь под venv, то просто можно сделать так
python3 -m pip install --upgrade pip python3 -m pip install jupyter
тут будет происходит неведома херня: запускаю в виртуальном окружении jupyter notebook, мне в ответ прилетает
[I 03:02:35.436 NotebookApp] Serving notebooks from local directory: /home/enot [I 03:02:35.436 NotebookApp] 0 active kernels [I 03:02:35.436 NotebookApp] The Jupyter Notebook is running at: [I 03:02:35.436 NotebookApp] http://localhost:8888/?token=4f5d7ce48936297318b86b9767e2187e6a5aadaa9000b894 [I 03:02:35.437 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [C 03:02:35.437 NotebookApp] Copy/paste this URL into your browser when you connect for the first time, to login with a token: http://localhost:8888/?token=4f5d7ce48936297318b86b9767e2187e6a5aadaa9000b894 /usr/bin/xdg-open: 771: /usr/bin/xdg-open: x-www-browser: not found /usr/bin/xdg-open: 771: /usr/bin/xdg-open: firefox: not found /usr/bin/xdg-open: 771: /usr/bin/xdg-open: iceweasel: not found /usr/bin/xdg-open: 771: /usr/bin/xdg-open: seamonkey: not found /usr/bin/xdg-open: 771: /usr/bin/xdg-open: mozilla: not found /usr/bin/xdg-open: 771: /usr/bin/xdg-open: epiphany: not found /usr/bin/xdg-open: 771: /usr/bin/xdg-open: konqueror: not found /usr/bin/xdg-open: 771: /usr/bin/xdg-open: chromium-browser: not found /usr/bin/xdg-open: 771: /usr/bin/xdg-open: google-chrome: not foundт.е. приложка пытается открыть консольный браузер. В моем случае это был Lync и эффект от увиденного был ужасный. Это примерно как когда ты первый раз открываешь vim и не представляешь как из него выйти - так же первые разы просто рвал ssh сессию, как сельский буритино) В общем я был несколько в шоке от происходящего, а всего то надо явно указывать `jupyter notebook --no-browser --port=8888`. Ниже пара команд почитать справочную информацию
`jupyter -h` - Show help information, including available subcommands.
`jupyter --config-dir` - There you can find your {application} cofigs when run `jupyter {application} --generate-config`
`jupyter --paths` - All dirs in one commands
`jupyter --paths --json` -- json like output
`jupyter console -h` - configuration options
`jupyter kernelspec list` - list of available kernels
настройка
Такие грабли происходили, потому что сразу надо было прочитать про его console, делаем следующее
jupyter notebook --generate-config jupyter notebook password #hardpass
а теперь подправим конфиг `vim ~/.jupyter/jupyter_notebook_config.py` вот так:
c.NotebookApp.open_browser = False c.NotebookApp.port = 6745 c.NotebookApp.ip = '0.0.0.0' # Any ip
и можно уже ходить в приложение используя проброс портов по ssh. Это вполне рабочий вариант, но как то коряво.
jupyter hub
Это один из тех немногих способов сделать все не по уебански. Даже мульти-юзерность будет.
Вариантов реализации мульти-юзер доступа много, но самый адекватный вариант - придется пакеты ставить глобально
requirements
sudo apt-get install npm nodejs-legacy -y python3 -m pip install jupyterhub sudo useradd rhea sudo pip install sudospawner sudo npm install -g configurable-http-proxy
user config
добавим группу для пользаков. Если что, они уже были в системе
sudo addgroup jupyterhub sudo usermod -a -G jupyterhub enot sudo usermod -a -G jupyterhub lisa groups | grep jupyterhub
возможно надо будет вылогиниться. Через `sudo visudo` добавляем возможность запуска
Runas_Alias JUPYTER_USERS = rhea, enot, lisa, stup Cmnd_Alias JUPYTER_CMD = /usr/local/bin/sudospawner rhea ALL=(JUPYTER_USERS) NOPASSWD:JUPYTER_CMD rhea ALL=(%jupyterhub) NOPASSWD:JUPYTER_CMD
а потом проверяем командой `sudo -u rhea sudo -n -u $USER /usr/local/bin/sudospawner --help`
Теперь добавляем PAM авторизацию
ls -l /etc/shadow sudo groupadd shadow sudo chgrp shadow /etc/shadow sudo chmod g+r /etc/shadow ls -l /etc/shadow sudo usermod -a -G shadow rhea sudo setcap 'cap_net_bind_service=+ep' /usr/bin/nodejstest via `sudo -u rhea python3 -c "import pamela, getpass; print(pamela.authenticate('$USER', getpass.getpass()))"`
server config
сначала делаем его окружение
sudo mkdir /etc/jupyterhub sudo chown rhea /etc/jupyterhub sudo mkdir /var/log/jupyterhub/ sudo touch /var/log/jupyterhub/hub.log chown -R rhea:shadow /var/log/jupyterhub/ cd /etc/jupyterhub
проверяем командой `sudo -u rhea jupyterhub --JupyterHub.spawner_class=sudospawner.SudoSpawner`
Если все нормас, то потом генерим конфиг, что бы не заниматься херней в консоли
sudo su jupyterhub --generate-config mv jupyterhub_config.py jupyterhub_config.py.old sudo cat </etc/jupyterhub/jupyterhub_config.py c.JupyterHub.active_server_limit = 10 c.JupyterHub.concurrent_spawn_limit = 5 c.JupyterHub.base_url = '/jupyter/' c.JupyterHub.spawner_class = 'sudospawner.SudoSpawner' c.JupyterHub.port = 6535 c.Authenticator.admin_users = {'enot'} c.JupyterHub.extra_log_file = '/var/log/jupyterhub/hub.log' EOT # ctrl+D
открываем лог `tail -f /var/log/jupyterhub/hub.log` в одной консоли
и проверяем командой `sudo -u rhea jupyterhub` в другой
и заходим по адресу http://buben.lan:6535/jupyter/
демонизация
Вообще я обычно демонизирую женщин, но тут я намерен проделать это с приложкой (с). По мотивам /jupyterhub/wiki
делаем `sudo vim /etc/systemd/system/jupyterhub.service`
[Unit] Description=JupyterHub After=network-online.target [Service] User=rhea Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin" ExecStart=/usr/local/bin/jupyterhub WorkingDirectory=/etc/jupyterhub [Install] WantedBy=multi-user.target
потом докинем библиотеки в системные файлы
ls -la /etc/systemd/system/jupyterhub.service sudo cp /lib/systemd/system/jupyterhub.service /etc/systemd/system/jupyterhub.service ls -la /lib/systemd/system/jupyterhub.service
далее подгружаем новый конфиг с сервисы и магия должна заработать
sudo systemctl daemon-reload sudo systemctl start jupyterhub sudo systemctl status jupyterhub
характерным признаком должно быть, что последняя команда показывает активный процесс
autostarup
в афтербут сервис добавляется командой `sudo systemctl enable jupyterhub.service`
web-app
у нас есть приготовленный nginx с https терминированием. Только благодаря этому не надо городить кучу конфигов на виртуалке и мудохаться с перевыпуском сертификата за натом. И если мы хотим иметь веб приложение jupyter по адресу `https://box.now.io/jupyter/`, то надо добавить в конфиг такой локэйшн
location /jupyter/ { proxy_pass http://buben.lan:6535; default_type application/octet-stream; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Origin ""; }
Есть пара интересных рекомендаций, как можно сделать еще, у этого улыбчивого парня
http://nathan.vertile.com/blog/2017/12/07/run-jupyter-notebook-behind-a-nginx-reverse-proxy-subpath/
но я забил, работает и ладно.
лайфхак для ленивых `sed -i 's/\r$//' nginx.conf`
и рестартануть веб-сервер `/etc/init.d/nginx reload`
database connect
Поставить довольно просто для postgre довольно просто
sudo add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -sc)-pgdg main" wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - sudo apt-get update sudo apt-get install postgresql-client-9.6 -y # собсно только ради этого все и затевалось sudo apt-get install postgresql postgresql-contrib -y # какие то очень нужные модули sudo apt-get install pgadmin3 -Y #веб-клиент, довольно не удобный уж лучше поставьте DataGrip с паленым серером лицензирования sudo apt-get install postgresql-9.6 -y # ну и почему бы до кучи саму базу не поставить sudo pip install psycopg2-binary sudo -u postgres psql
Далее надо настроить тестового пользователя
create user bender with password 'test1'; create database bender owner bender; grant all privileges on database bender to bender;
теперь пробуем подключиться в консоли из под своего робота `sudo -u bender psql`
create schema report authorization bender; CREATE TABLE report.play2 ( equip_id serial PRIMARY KEY, type varchar (50) NOT NULL, color varchar (25) NOT NULL, location varchar(25) check (location in ('north', 'south', 'west', 'east', 'northeast', 'southeast', 'southwest', 'northwest')), install_date date ); \dt alter table report.play2 owner to bender; insert into report.play2 (type, color, location, install_date) values ('blabla', 'blue', 'north', current_date) ; select * from report.play2; \dt \q
теперь пробуем из под jupyterhub в ноутбуке используя psycopg пробуем
import psycopg2 import sys dsn_database = "bender" dsn_hostname = "localhost" dsn_port = "5432" dsn_uid = "bender" dsn_pwd = "test1" try: conn_string = "host="+dsn_hostname+" port="+dsn_port+" dbname="+dsn_database+" user="+dsn_uid+" password="+dsn_pwd print("Connecting to database\n ->%s" % (conn_string)) conn=psycopg2.connect(conn_string) print("Connected!\n") except: print("Unable to connect to the database.") cursor = conn.cursor() cursor.execute("""SELECT datname from pg_database""") rows = cursor.fetchall() print("\nShow me the databases:\n") for row in rows: print(" ", row[0])