{"id":18303494,"url":"https://github.com/gosecure/jupyterhub-workshop-environment","last_synced_at":"2025-04-09T10:17:59.370Z","repository":{"id":207020502,"uuid":"716259645","full_name":"GoSecure/jupyterhub-workshop-environment","owner":"GoSecure","description":"Opinionated JupyterHub deployment for workshops relying on GitHub for Authentication","archived":false,"fork":false,"pushed_at":"2023-11-13T17:12:16.000Z","size":427,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-02-15T04:26:33.835Z","etag":null,"topics":["jupyter-notebook","jupyterhub","jupyterlab","workshop"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GoSecure.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-11-08T19:06:24.000Z","updated_at":"2024-12-16T14:42:31.000Z","dependencies_parsed_at":"2023-11-13T18:29:29.084Z","dependency_job_id":"bfcb06f4-b5bd-4400-96fd-903c0f645a02","html_url":"https://github.com/GoSecure/jupyterhub-workshop-environment","commit_stats":null,"previous_names":["gosecure/jupyterhub-workshop-environment"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoSecure%2Fjupyterhub-workshop-environment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoSecure%2Fjupyterhub-workshop-environment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoSecure%2Fjupyterhub-workshop-environment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoSecure%2Fjupyterhub-workshop-environment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GoSecure","download_url":"https://codeload.github.com/GoSecure/jupyterhub-workshop-environment/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248018097,"owners_count":21034052,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jupyter-notebook","jupyterhub","jupyterlab","workshop"],"created_at":"2024-11-05T15:25:51.204Z","updated_at":"2025-04-09T10:17:59.353Z","avatar_url":"https://github.com/GoSecure.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"= README\n\nOpionated JupyterHub deployment for workshops relying on GitHub for Authentication and Digital Ocean as the infrastructure provider.\n\nThis is a drastic departure of our previous environment available here: https://github.com/GoSecure/jupyterhub-workshop-environment-legacy\n\nFeatures:\n\n* Supports JupyterLab and Jupyter Notebook (Python and Terminals)\n* Read-only shared files to all users (in users' homes)\n* Writeable and shared scratch directory available to all users (in users' homes)\n* Users have their own copies of notebook, created on first login from a template directory\n* Server deployed and managed by Terraform\n* Out of the box LetsEncrypt HTTPS\n* Very close to upstream https://tljh.jupyter.org/[The Littlest JupyterHub (TLJH)] should make upgrades seamless\n\nOriginally forked from https://github.com/jupyterhub/jupyterhub-deploy-docker[jupyterhub-deploy-docker] in 2017 but little left if anything today.\n\n\n== Setup Instructions\n\n=== Prepare for Deployment\n\nThese steps should be done locally before provisioning the JupterHub\nserver to facilitate deployment.\n\n==== Setup GitHub Authentication\n\nCreate a GitHub application reflecting the purpose of your JupyterHub\nworkshop. It will be used to allow users to login and gain access to\nthe workshop servers. You should know the following information ahead\nof time:\n\n* Workshop Name (Application Name)\n* Workshop Server URL (Doesn't need to resolve yet)\n* Workshop Description\n* Workshop Icon if desired.\n\n*NOTE*: Applications for workshops should be created under your organization at\nhttps://github.com/organizations/\u003corgname\u003e/settings/applications/new\n\nAsk organisation admin to create the application with the required information.\n\nPopulate `terraform.tfvars` with the following content:\n\n  github_client_id  = \"\u003cgithub_client_id\u003e\"\n  github_client_secret = \"\u003cgithub_client_secret\u003e\"\n  # GitHub Oauth Callback will be set to https://\u003cworkshop_domain\u003e/hub/oauth_callback by default\n  #github_oauth_callback = \"https://\u003cmyhost.mydomain\u003e/hub/oauth_callback\"\n\nBy default our setup is open to anyone to create an account like for an open\nworkshop with no pre-registrations (different options available below).\n\n==== Setup Administrator Accounts\n\nThe first administrator account is configured in the `terraform.tfvars` file with `jupyterhub_admin`.\nIt must be a GitHub username. Once authenticated this user will be an administrator.\nOther admin accounts are configured in the `/opt/tljh/config/config.yaml` file.\nThe administration GUI (`/hub/admin`) also allows you to elevate accounts via \"Edit\".\nThese accounts can use `sudo` without a password.\n\n==== Workshop Files\n\nThere are three ways to expose files to the workshop attendees.\n\nFiles exposed to attendees all rely to using the Linux `/etc/skel/` home directory template. Remember: once the user is created, things in `skel` will not be copied again. You must destroy a user for it to be recreated (see instructions below under \"Operational Procedures\").\n\n===== Read-only shared with all participants\n\n* Locally: `workshop-data/`\n* Deployed to: `/srv/workshop/`\n* Available to participants as: `workshop-readonly/` in their home directory\n\nAll users will have access to a directory in their own homes (`/home/jupyter-\u003cgithub_username\u003e/`) called `workshop-readonly/` that will be mapped to the servers' `/srv/workshop/`.\n\nChanges made in `/srv/workshop/*` will be reflected instantly to all participants.\n\nThis is accomplished via a symlink in `/etc/skel/`.\n\n===== Files for participants (writable and executable)\n\n* Locally: `workshop-data/assignments/`\n* Deployed to: `/srv/workshop/assignments` and `/etc/skel/your-personal-lab/`\n* Available to participants as: `your-personal-lab/` in their home directory\n\nOn container creation, a directory called `your-personal-lab/` will be created and\npopulated from the servers' `/etc/skel/your-personal-lab/` content.\n\n===== Scratch for participants (shared and writable)\n\n* Locally: None\n* On the server: `/srv/scratch/`\n* Available to participants as: `scratch/` in their home directory\n\nA `scratch/` directory is available in users' home which is world-writable.\nCreator ownership is retained, you can't alter someone else's files but you can read them.\n\nEnabled by the https://github.com/kafonek/tljh-shared-directory[tljh-shared-directory] plugin.\n\n\n=== Deploying the Server\n\nEnsure that you have a recent version of Terraform installed and get it ready:\n\n    terraform init\n\nConfigure your Digital Ocean credentials and other settings in `terraform.tfvars`:\n\n----\n# the following values are used as tags in digital ocean so only lowercase, dash and underscore allowed\nworkshop_name = \"\u003cworkshop-name\u003e\"\ntag_owner = \"\u003cusername\u003e\"\ntag_event = \"\u003cevent-name\u003e\"\ndo_token = \"\u003cyour DO token\u003e\"\n# default is 1 CPU 2 GB, you can find droplet sizes here: https://slugs.do-api.dev/\n#instance_size = \"c-4\"\n# default region is Toronto (tor1)\ninstance_region = \"nyc3\"\njupyterhub_admin = \"\u003cgithub-username\u003e\"\n# A URL to a Python requirements.txt file for dependencies to be installed on the system\nworkshop_requirements_url = \"\u003cURL\u003e\"\n\n# GitHub Authentication Parameters\ngithub_client_id  = \"\u003cgithub_client_id\u003e\"\ngithub_client_secret = \"\u003cgithub_client_secret\u003e\"\n----\n\nSpawn and provision the droplet. It might take a while to setup and provision, so be patient.\n\n    terraform validate\n    terraform plan\n    terraform apply\n\nNOTE: During the apply, you should hurry up and update the DNS of `workshop_domain` to point to the newly deployed droplet public IP.\n      Failure to do so will end-up in repeated Let's Encrypt certificate creation failures and will result in a block of one hour before you can attempt to create the certificate again.\n      If it happens. Shutdown jupyterhub, make sure DNS has propagated and start jupyterhub again after one hour.\n\n=== Server-Side Configuration\n\nTo connect to the server via SSH, run:\n\n    ./bin/ssh-connect.sh\n\n=== More Customization\n\nAt this point you have a 100% standard TLJH installation.\nYou can rely on their documentation to further customize the installation:\n\n* https://tljh.jupyter.org/en/latest/howto/index.html[How-To Guides]\n* https://tljh.jupyter.org/en/latest/topic/customizing-installer.html#installing-python-packages-in-the-user-environment[Installing more packages in the environment]\n* https://tljh.jupyter.org/en/latest/topic/index.html[Topic Guides]\n* https://tljh.jupyter.org/en/latest/troubleshooting/index.html[Troubleshooting]\n\n\n== Operational Procedures\n\n=== Upgrading JupyterHub\n\nRe-running the TLJH installer should upgrade JupyterHub\n\n=== Deleting a user\n\nThis is useful when testing the initial setup of a user's home directory.\n\n* In the `/hub/admin` GUI: Edit User -\u003e Delete\n* In a root shell: `userdel -r jupyter-\u003cusername\u003e`\n\n=== Reveal Solutions\n\nFrom an admin notebook:\n\n    !sudo chmod go+rx /srv/workshop/solutions/\n    !sudo chmod go+r /srv/workshop/solutions/*\n\nFrom an admin shell:\n\n    sudo chmod go+rx /srv/workshop/solutions/\n    sudo chmod go+r /srv/workshop/solutions/*\n\n\n== Debugging\n\n=== Logging\n\nUsing `systemctl status` on the jupyterhub or traefik services:\n\n    systemctl status jupyterhub\n\nChecking the logs with `journalctl`:\n\n    journalctl -f -u traefik\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgosecure%2Fjupyterhub-workshop-environment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgosecure%2Fjupyterhub-workshop-environment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgosecure%2Fjupyterhub-workshop-environment/lists"}