> ## Documentation Index
> Fetch the complete documentation index at: https://anaconda.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Installing JupyterHub

export const Comments = ({children}) => {
  return <div class="my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border border-zinc-500/20 bg-zinc-50/50 dark:border-zinc-500/30 dark:bg-zinc-500/10" data-callout-type="comments">
      <div class="w-4">
        <svg width="14" height="14" viewBox="0 0 640 640" fill="currentColor" xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" aria-label="Comments">
            <path d="M320 112C434.9 112 528 205.1 528 320C528 434.9 434.9 528 320 528C205.1 528 112 434.9 112 320C112 205.1 205.1 112 320 112zM320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM280 400C266.7 400 256 410.7 256 424C256 437.3 266.7 448 280 448L360 448C373.3 448 384 437.3 384 424C384 410.7 373.3 400 360 400L352 400L352 312C352 298.7 341.3 288 328 288L280 288C266.7 288 256 298.7 256 312C256 325.3 266.7 336 280 336L304 336L304 400L280 400zM320 256C337.7 256 352 241.7 352 224C352 206.3 337.7 192 320 192C302.3 192 288 206.3 288 224C288 241.7 302.3 256 320 256z" />
        </svg>
      </div>
      <div class="text-sm prose min-w-0 w-full">
        {children}
      </div>
    </div>;
};

export const Danger = ({children}) => {
  return <div class="callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border danger-admonition dark:danger-admonition" data-callout-type="danger">
      <div class="mt-0.5 w-4">
        <svg width="14" height="14" viewBox="0 0 14 14" fill="rgb(239, 68, 68)" xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 text-sky-500" aria-label="Danger">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
      </div>
      <div class="text-sm prose min-w-0 w-full">
        {children}
      </div>
    </div>;
};

## Prerequisites

Before you begin, make sure you have the following:

* An organization on Anaconda.com with a current subscription.
* A Linux server that meets the [system requirements](/anaconda-platform/cloud/admin/integrations/jupyterhub/sys-reqs-and-env-prep).

## Installing JupyterHub

<Steps>
  <Step title="Download and unpack the installer">
    1. Log in to your Linux server as a root user.

    2. Download the installer by running the following command:

       ```sh theme={null}
       curl -O <INSTALLER_LOCATION>
       ```

           <Comments>
             Replace \<INSTALLER\_LOCATION> with the provided location of your installer.
           </Comments>

    3. Unpack the installer tarball:

       ```sh Example theme={null}
       tar -xvf jupyterhub-<VERSION>-<HASH>.tar
       ```
  </Step>

  <Step title="Gather your SSL/TLS certificate information">
    Locate your SSL/TLS `.crt` and `.key` files and note their paths for later use.

    If you don't have valid SSL/TLS certificates, you can proceed by using the `DIY-SSL-CA` package (included with the installer):

    <Danger>
      The self-signed certificates created by the `DIY-SSL-CA` package can reduce your time to first use of JupyterHub, *but should be replaced with valid certificates from a trusted certificate authority as soon as possible*. Do not use self-signed certificates in production environments!
    </Danger>

    ```sh theme={null}
    cd DIY-SSL-CA
    bash create_noprompt.sh <HOSTNAME>
    ```

    <Comments>
      Replace \<HOSTNAME> with your JupyterHub server hostname.
    </Comments>

    The `create_noprompt.sh` script generates the files that you'll reference later as environment variables at the following directory locations:

    * `DIY-SSL-CA/CA/ca.crt`
    * `DIY-SSL-CA/out/<HOSTNAME>/<HOSTNAME>-bundle.crt`
    * `DIY-SSL-CA/out/<HOSTNAME>/<HOSTNAME>.key`

    <Note>
      `<HOSTNAME>` is your JupyterHub server hostname.
    </Note>
  </Step>

  <Step title="Create a service account">
    Create a dedicated service account for the JupyterHub services to use to authenticate to your organization members.

    1. [Sign in to Anaconda.com](https://auth.anaconda.com/ui/login?return_to=https://anaconda.com/app/).
    2. [Navigate to your Organizations page](https://anaconda.com/app/profile/organizations).
    3. Select the organization you want to create a service account for.
    4. Under User Management, select <Icon icon="bullseye-pointer" iconType="regular" /> **Service Accounts**.
    5. Click <Icon icon="plus" iconType="regular" /> **Add Account**.
    6. Name for your service account JupyterHub.
    7. Click **Save**.
    8. Save the **Client ID** and **Client Secret** in a secure location.
  </Step>

  <Step title="Add your OAuth callback URL">
    [Submit a request](https://support.anaconda.com/hc/en-us/requests/new?ticket_form_id=360000993773) to add your OAuth callback URL to the JupyterHub service account. Complete the request form as follows:

    1. Enter your email address.

    2. Enter "JupyterHub OAuth callback URL" as the subject.

    3. In the description, provide your JupyterHub server's fully qualified domain name.

           <Note>
             If you have modified your `jupyterhub_config.py`'s config class variable (`c.AnacondaServerAuthenticator.oauth_callback_url`), include the modified value in the description.
           </Note>

    4. Select *All users* as the user impact.

    5. Select *Low* as the priority.

    6. Select *Anaconda Platform (Cloud)* as the product.

    7. Enter `N/A` as the product version.

    8. Select *Production* as the system type.

    9. Select *Integration* as the ticket type.

    10. Click **Submit**.

    <Note>
      You will receive an email when your request is approved. You can continue with the installation process while you wait for the request to be approved, but users will not be able to log into the JupyterHub server until your request is approved.
    </Note>
  </Step>

  <Step title="Create an environment file">
    Create an environment file named `.env` in your `/home/<username>/` directory.

    <Note>
      If you already have an `.env` file in your home directory, you can name your new file something else, like `.env_jhub_anaconda`.
    </Note>

    Add the following environment variables to the `.env` file you just created, and populate them with the values you gathered in the previous steps:

    ```sh theme={null}
    CLIENT_ID= <CLIENT_ID>
    CLIENT_SECRET= <CLIENT_SECRET>
    CERT= <PATH_TO_CERT>
    KEY= <PATH_TO_KEY>
    CA_CERT= <PATH_TO_CA_CERT> 
    JUPYTERHUB_SPAWNER_TYPE=<SPAWNER_TYPE>
    REPO_CHANNELS= ("org_chan1" "org_chan2" "defaults")
    ```

    <Comments>
      Replace \<CLIENT\_ID> with your service account client ID.<br />
      Replace \<CLIENT\_SECRET> with your service account client secret.<br />
      Replace \<PATH\_TO\_CERT> with the path to your SSL/TLS certificate file.<br />
      Replace \<PATH\_TO\_KEY> with the path to your SSL/TLS key file.<br />
      Replace \<PATH\_TO\_CA\_CERT> with the path to your CA certificate file (self-signed certificates only).<br />
      Replace \<SPAWNER\_TYPE> with your JupyterHub spawner type: local|systemd. Defaults to systemd if not supplied.
    </Comments>

    <Note>
      The `REPO_CHANNELS` variable is a list of <Tooltip tip="A location (URL or file path) in a repository where conda looks for packages.">channels</Tooltip> that the JupyterHub services will use to install <Tooltip tip="Software files and information about the software, such as its name, version, and description, bundled into a file that can be installed and managed by a package manager.">packages</Tooltip> when users build new <Tooltip tip="A self-contained, isolated space for installing and running software packages.">environments</Tooltip> in Jupyter. The installer configures conda to respect the priority of the channels in the order they are listed in the environment file.
    </Note>
  </Step>

  <Step title="Run the installer">
    Run the installation command:

    ```sh theme={null}
    sudo ENV_FILE=<PATH_TO_ENV_FILE> ./jupyterhub-<VERSION>-<HASH>.sh -b
    ```

    <Comments>
      Replace \<PATH\_TO\_ENV\_FILE> with the path to the environment file you just created.<br />
      Replace \<VERSION> with your installer version.<br />
      Replace \<HASH> with your installer hash.
    </Comments>
  </Step>
</Steps>

## Troubleshooting

### I am receiving a `libcrypt.so.1` error post installation

<AccordionGroup>
  <Accordion title="Cause">
    Amazon Linux does not include `libxcrypt-compat`, which causes nginx services to error when starting.
  </Accordion>

  <Accordion title="Solution">
    If you receive a `libcrypt.so.1` error post installation, install the `libxcrypt-compat` package on your JupyterHub server:

    ```sh theme={null}
    sudo yum install libxcrypt-compat
    ```

    After installing the package, restart the nginx service:

    ```sh theme={null}
    sudo systemctl restart nginx.service
    ```
  </Accordion>
</AccordionGroup>

### SystemD version too old or unavailable, using local spawner

<AccordionGroup>
  <Accordion title="Cause">
    This warning occurs when JupyterHub is installed on a Linux system running `systemd < 245`. In this case, JupyterHub defaults to using the local spawner instead of systemdSpawner, and resource management is not enabled.
  </Accordion>

  <Accordion title="Solution">
    JupyterHub requires `systemd >= 245` or later for full resource management support.

    Verify your systemd version by running the following command:

    ```sh theme={null}
    systemctl --version
    ```

    If necessary, update your operating system to a Linux distribution that provides `systemd >= 245`.
  </Accordion>
</AccordionGroup>
