Base terraform template to deploy a JupyterLab application on an AWS EC2 instance.
Project description
Jupyter Deploy AWS EC2 base template
The Jupyter Deploy AWS EC2 base template is an open-source project to run JupyterLab applications on remote hosts served on your domain with encrypted HTTP (TLS), GitHub OAuth integration, real-time-collaboration, and fast UV-based environments. It uses Terraform as the infrastructure-as-code engine, deploys the JupyterLab container to an Amazon EC2 instance, and controls access with GitHub identities. It places the EC2 instance in the default VPC of your AWS account and adds a DNS record to your domain with Amazon Route53.
Within the EC2 instance, it leverages docker-compose to run a jupyter service, a traefik sidecar to control ingress and an oauth2-proxy middleware to handle oauth with traefik ForwardAuth protocol. The instance only allows ingress on port 443 (HTTPS), and relies on the ssm-agent for administrator operations. Refer to AWS SSM for more details.
This base template is maintained and supported by AWS.
Prerequisites
- a domain that you own verifiable by Amazon Route 53
- instructions to register a domain
- instructions to buy a domain
- a GitHub OAuth App
- register a new application
- choose any application name
- set
Homepage URLto:https://<subdomain>.<domain> - set
Authorization callback URLto:https://<subdomain>.<domain>/oauth2/callback - documentation to dive deeper
- write down and save your app client ID and client secret
- select at least one of the following GitHub identities to authorize:
- a GitHub username (or a list of usernames)
- a GitHub organization whose members; optionally restrict further by GitHub teams
Usage
This terraform project is meant to be used with the jupyter-deploy CLI.
Installation (with pip):
Recommended: create or activate a python virtual environment.
pip install jupyter-deploy[aws]
pip install jupyter-deploy-tf-aws-ec2-base
Project setup
mkdir my-jupyter-deployment
cd my-jupyter-deployment
jd init . -E terraform -P aws -I ec2 -T base
Consider making my-jupyter-deployment a git repository.
Configure and create the infrastructure
jd config
jd up
Access your JupyterLab application
# verify that your host and containers are running
jd host status
jd server status
# open your application on your web browser
jd open
Manage access
# By GitHub users
jd users list
jd users add USERNAME1 USERNAME2
jd users remove USERNAME1
# By GitHub organization
jd organization get
jd organization set ORGANIZATION
jd organization unset
# Along with GitHub organization, by teams
jd teams list
jd teams add TEAM1 TEAM2
jd teams remove TEAM2
Temporarily stop/start your EC2 instance
# To stop your instance
jd host stop
jd host status
# To start it again
jd host start
jd server start
jd server status
Manage your EC2 instance
# connect to your host
jd host connect
# disconnect
exit
Take down all the infrastructure
This operation removes all the resources associated with this project in your AWS account.
jd down
Details
This project:
- places the instance in the first subnet of the default VPC
- selects the latest Amazon Linux 2023 AMI compatible with the selected instance type
- standard AL2023 AMI for CPU instances (x86_64 or arm64)
- DLAMI in the case of GPU or Neuron instances (x86_64 or arm64)
- sets up an IAM role to enable SSM, Route53, S3, and (optionally) EFS access
- passes on the root volume settings of the AMI
- adds an EBS volume which will mount on the Jupyter Server container
- adds an Elastic IP (EIP) to keep the public IP of the instance stable
- creates an S3 bucket to store deployment configuration files
- upload various bash scripts and docker service configuration files
- cloudinit script pulls the configuration files at instance setup or update time
- writes Docker service logs to disk at
/var/log/servicesusingfluent-bit - configures automatic rotation for all log files using
logrotate - creates an SSM instance-startup script, which references several files:
cloudinit.sh.tftplto configure the EC2 instancedocker-compose.yml.tftplto configure the Docker servicesdocker-startup.sh.tftplto start the Docker servicescloudinit-volumes.sh.tftplto optionally mount additional elastic block store (EBS) or elastic file systems (EFS)traefik.yml.tftplto configure traefikdockerfile.jupyterto build the Jupyter containerjupyter-start.shto provide entrypoint script for the Jupyter containerjupyter-reset.shto provide a fallback if the Jupyter container fails to startpyproject.jupyter.tomlto configure the Python dependencies of the base environment where the Jupyter server runs- note:
pixi.jupyter.tomlif you selectpixias dependency manager
- note:
jupyter_server_config.pyto configure Jupyter serverdockerfile.logrotatorto configure the sidecar container rotating log files on disklogrotator-start.sh.tftplto configure logrotatefluent-bit.confto configure the fluent-bit service writing Docker service logs to/var/log/servicesparsers.confto configure the fluent-bit Docker parserscheck-status-internal.shto verify that the services are up and the TLS certificates are availableget-status.shto translate the return code ofcheck-statusscript to a human-readable statusupdate-auth.shto update the authorized org, teams, and/or usersget-auth.shto retrieve the authorized org, teams, and/or usersupdate-server.shto update the services running within the hostrefresh-oauth-cookie.shto rotate the oauth cookie secret and invalidate all issued cookies
- creates an SSM association, which runs the startup script on the instance
- creates the Route 53 Hosted Zone for the domain unless it already exists
- adds the DNS record to the Route 53 Hosted Zone
- creates an AWS Secret to store the OAuth App client secret
- creates an AWS Secret to store TLS certificates from Let's Encrypt for persistence across instance replacements
- optionally creates or references EBS volumes or EFS and mount them to the home directory of the jupyter app
- provides two presets default values for the template variables:
defaults-all.tfvarscomprehensive preset with all the recommended valuesdefaults-base.tfvarsmore limited preset; it will prompt user to select the instance type and volume size
- creates AWS SSM documents for jupyter-deploy commands
Requirements
| Name | Version |
|---|---|
| terraform | >= 1.0 |
| aws | >= 4.66 |
Providers
| Name | Version |
|---|---|
| aws | >= 4.66 |
Modules
| Name | Location |
|---|---|
ami_al2023 |
template/engine/modules/ami_al2023 |
certs_secret |
template/engine/modules/certs_secret |
ec2_iam_role |
template/engine/modules/ec2_iam_role |
ec2_instance |
template/engine/modules/ec2_instance |
network |
template/engine/modules/network |
s3_bucket |
template/engine/modules/s3_bucket |
secret |
template/engine/modules/secret |
volumes |
template/engine/modules/volumes |
Resources
| Name | Type |
|---|---|
| aws_security_group | resource |
| aws_instance | resource |
| aws_iam_role | resource |
| aws_iam_role_policy_attachment | resource |
| aws_iam_instance_profile | resource |
| aws_ebs_volume | resource |
| aws_volume_attachment | resource |
| aws_ssm_document | resource |
| aws_ssm_association | resource |
| aws_route53_zone | resource |
| aws_route53_record | resource |
| aws_secretsmanager_secret | resource |
| aws_iam_policy | resource |
| aws_ssm_parameter | resource |
| null_resource | resource |
| aws_default_vpc | resource |
| aws_ebs_volume | resource |
| aws_efs_file_system | resource |
| aws_efs_mount_target | resource |
| aws_eip | resource |
| aws_s3_bucket | resource |
| aws_s3_bucket_versioning | resource |
| aws_s3_bucket_server_side_encryption_configuration | resource |
| aws_s3_bucket_public_access_block | resource |
| aws_s3_object | resource |
| aws_subnets | data source |
| aws_subnet | data source |
| aws_ami | data source |
| aws_route53_zone | data source |
| aws_ebs_volume | data source |
| aws_efs_file_system | data source |
| aws_iam_policy | data source |
| aws_iam_policy_document | data source |
| local_file | data source |
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| region | string |
us-west-2 |
The AWS region where to create the resources |
| instance_type | string |
t3.medium |
The type of instance to start |
| key_pair_name | string |
null |
The name of key pair |
| ami_id | string |
null |
The ID of the AMI to use for the instance |
| min_root_volume_size_gb | number |
30 |
The minimum size in gigabytes of the root EBS volume for the EC2 instance (will use AMI snapshot size if larger) |
| volume_size_gb | number |
30 |
The size in GB of the EBS volume the Jupyter Server has access to |
| volume_type | string |
gp3 |
The type of EBS volume the Jupyter Server will has access to |
| iam_role_prefix | string |
Jupyter-deploy-ec2-base |
The prefix for the name of the IAM role for the instance |
| oauth_app_secret_prefix | string |
Jupyter-deploy-ec2-base |
The prefix for the name of the AWS secret to store your OAuth app client secret |
| s3_bucket_prefix | string |
jupyter-deploy-ec2-base |
The prefix for the name of the S3 bucket where deployment scripts are stored (3-28 characters, lowercase alphanumeric with hyphens) |
| certs_secret_prefix | string |
Jupyter-deploy-ec2-base |
The prefix for the name of the AWS secret where ACME certificates are stored |
| letsencrypt_email | string |
Required | An email for letsencrypt to notify about certificate expirations |
| domain | string |
Required | A domain that you own |
| subdomain | string |
Required | A sub-domain of domain to add DNS records |
| oauth_provider | string |
github |
The OAuth provider to use |
| oauth_allowed_org | string |
"" |
The GitHub organization to allowlist |
| oauth_allowed_teams | list(string) |
[] |
The list of GitHub teams to allowlist |
| oauth_allowed_usernames | list(string) |
[] |
The list of GitHub usernames to allowlist |
| oauth_app_client_id | string |
Required | The client ID of the OAuth app |
| oauth_app_client_secret | string |
Required | The client secret of the OAuth app |
| log_files_rotation_size_mb | number |
50 |
The size in megabytes at which to rotate log files |
| log_files_retention_count | number |
10 |
The maximum number of rotated log files to retain for a log group |
| log_files_retention_days | number |
180 |
The maximum number of days to retain any log files |
| custom_tags | map(string) |
{} |
The custom tags to add to all the resources |
| additional_ebs_mounts | list(map(string)) |
[] |
Elastic block stores to mount on the notebook home directory |
| additional_efs_mounts | list(map(string)) |
[] |
Elastic file systems to mount on the notebook home directory |
Outputs
| Name | Description |
|---|---|
jupyter_url |
The URL to access your notebook app |
auth_url |
The URL for the OAuth callback - do not use directly |
instance_id |
The ID of the EC2 instance |
ami_id |
The Amazon Machine Image ID used by the EC2 instance |
jupyter_server_public_ip |
The public IP assigned to the EC2 instance |
secret_arn |
The ARN of the AWS Secret storing the OAuth client secret |
certs_secret_arn |
The ARN of the AWS Secret where TLS certificates are stored |
deployment_scripts_bucket_name |
Name of the S3 bucket where deployment scripts and service configuration files are stored |
deployment_scripts_bucket_arn |
ARN of the S3 bucket where deployment scripts and service configuration files are stored |
region |
The AWS region where the resources were created |
deployment_id |
Unique identifier for this deployment |
images_build_hash |
Hash of files affecting docker compose image builds (jupyter, log-rotator) |
scripts_files_hash |
Hash of all deployment script files which controls SSM association re-execution |
server_status_check_document |
Name of the SSM document to verify if the server is ready to serve traffic |
server_update_document |
Name of the SSM document to control server container operations |
server_logs_document |
Name of the SSM document to print server logs to terminal |
server_exec_document |
Name of the SSM document to execute commands inside server containers |
server_connect_document |
Name of the SSM document to start interactive shell sessions inside server containers (jupyter or traefik) |
auth_org_unset_document |
Name of the SSM document to remove the allowlisted organization |
auth_check_document |
Name of the SSM document to view authorized users, teams and organization |
auth_users_update_document |
Name of the SSM document to change the authorized users |
auth_teams_update_document |
Name of the SSM document to change the authorized teams |
auth_org_set_document |
Name of the SSM document to allowlist an organization |
auth_org_unset_document |
Name of the SSM document to remove the allowlisted organization |
persisting_resources |
List of identifiers of resources that should not be destroyed |
License
The Jupyter Deploy AWS EC2 base template is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jupyter_deploy_tf_aws_ec2_base-0.5.0.tar.gz.
File metadata
- Download URL: jupyter_deploy_tf_aws_ec2_base-0.5.0.tar.gz
- Upload date:
- Size: 92.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b603128c4c58607b5e43763378109423099af2558c68310bee84e59c1bddd29
|
|
| MD5 |
50dd8028ef251ab1082e850335c214e0
|
|
| BLAKE2b-256 |
c50b803bac5a06b613721fe598861c7e83b3f9bd6b40e2e740fe3c2be90b2664
|
File details
Details for the file jupyter_deploy_tf_aws_ec2_base-0.5.0-py3-none-any.whl.
File metadata
- Download URL: jupyter_deploy_tf_aws_ec2_base-0.5.0-py3-none-any.whl
- Upload date:
- Size: 85.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2df369759df7b8bbfcb7637f927e98e61fc21decde519a0a935d3e8457ea13ec
|
|
| MD5 |
3bd3d81a1a1bfb9968a76b745ed463a8
|
|
| BLAKE2b-256 |
04503f7f380afabd7b1e9fda28a49cbbfefb46d0866327836754b6b53b919c25
|