How to Install Jupyter Notebook on RHEL 7
Jupyter Notebook is a browser-based interactive computing environment used extensively in data science, machine learning, and scientific research. It allows you to write Python code, run it in cells, visualize data inline, and document your analysis—all in one place. This guide covers two installation methods on Red Hat Enterprise Linux 7: using pip with a Python virtual environment, and using the Anaconda distribution. It also explains how to configure Jupyter for remote access with password protection, SSL encryption, a systemd service for automatic startup, and an Nginx reverse proxy so the notebook is accessible through a standard HTTP/HTTPS port.
Prerequisites
- RHEL 7 server with sudo access
- Python 3.6 or later installed via
yum install python3or Anaconda - At least 1 GB of free RAM for running notebooks
- Nginx installed if you intend to use a reverse proxy
- Port 8888 accessible through the firewall, or Nginx configured on port 80/443
Step 1: Install Python 3 and pip
RHEL 7 ships with Python 2.7 by default. Install Python 3 from the RHEL Software Collections or EPEL repository before proceeding.
# Enable EPEL repository
sudo yum install epel-release
# Install Python 3.6 from EPEL
sudo yum install python36 python36-pip python36-devel
# Verify the installation
python3 --version
pip3 --version
Alternatively, if you have a Red Hat subscription, Python 3 is available via Software Collections:
sudo yum install rh-python36
scl enable rh-python36 bash
Step 2: Create a Virtual Environment and Install Jupyter
Create a dedicated virtual environment to isolate Jupyter and its dependencies:
python3 -m venv ~/jupyter-env
source ~/jupyter-env/bin/activate
pip install --upgrade pip
pip install jupyter notebook
Verify the installation succeeded:
jupyter --version
which jupyter
Step 3: Alternative — Install via Anaconda
Anaconda bundles Python, Jupyter, and hundreds of scientific packages in a single installer. Download and install it as follows:
# Download the Anaconda installer (check for the latest version at anaconda.com)
wget https://repo.anaconda.com/archive/Anaconda3-2024.02-1-Linux-x86_64.sh -O /tmp/anaconda.sh
# Verify the checksum (compare against the official hash)
sha256sum /tmp/anaconda.sh
# Run the installer
bash /tmp/anaconda.sh -b -p ~/anaconda3
# Add conda to PATH
echo 'export PATH="$HOME/anaconda3/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Install Jupyter (already included in Anaconda, but update if needed)
conda install jupyter notebook
Step 4: Generate the Jupyter Configuration File
Jupyter stores its runtime configuration in a file at ~/.jupyter/jupyter_notebook_config.py. Generate it with:
jupyter notebook --generate-config
The output will confirm the config file location:
Writing default config to: /root/.jupyter/jupyter_notebook_config.py
Step 5: Set a Notebook Password
Never expose a Jupyter Notebook without authentication. Generate a hashed password to use in the configuration:
jupyter notebook password
You will be prompted to enter and confirm a password. The hashed value is saved to ~/.jupyter/jupyter_notebook_config.json automatically. Alternatively, generate the hash manually to embed it in the config file:
python3 -c "from notebook.auth import passwd; print(passwd('your-password-here'))"
The output will look like: argon2:$argon2id$v=19$m=10240.... Copy this value for use in the next step.
Step 6: Configure Jupyter for Remote Access
Edit ~/.jupyter/jupyter_notebook_config.py and set the following options for secure remote access:
c.NotebookApp.ip = '127.0.0.1' # Listen on localhost only (Nginx will proxy)
c.NotebookApp.port = 8888
c.NotebookApp.open_browser = False # Do not open a browser on the server
c.NotebookApp.password = 'argon2:$argon2id$v=19...' # Paste the hash from Step 5
c.NotebookApp.allow_origin = '*' # Adjust if using a specific domain
c.NotebookApp.base_url = '/jupyter/' # URL prefix when using Nginx proxy
If you want Jupyter to bind directly on all interfaces without Nginx (less recommended), change ip to '0.0.0.0' and open port 8888 in the firewall.
Step 7: Enable SSL for Direct HTTPS Access
If you are running Jupyter without Nginx and need HTTPS, generate a self-signed certificate:
openssl req -x509 -nodes -days 365 -newkey rsa:2048
-keyout ~/.jupyter/jupyter.key
-out ~/.jupyter/jupyter.crt
-subj "/C=US/ST=State/L=City/O=Org/CN=yourdomain.com"
Then reference the certificate in the config file:
c.NotebookApp.certfile = '/root/.jupyter/jupyter.crt'
c.NotebookApp.keyfile = '/root/.jupyter/jupyter.key'
Step 8: Create a systemd Service for Jupyter
A systemd service ensures Jupyter starts on boot and restarts if it crashes. Create the unit file:
sudo tee /etc/systemd/system/jupyter.service <<'EOF'
[Unit]
Description=Jupyter Notebook Server
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/root/notebooks
ExecStart=/root/jupyter-env/bin/jupyter notebook
--config=/root/.jupyter/jupyter_notebook_config.py
Restart=on-failure
RestartSec=10s
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
Create the notebooks directory, then enable and start the service:
mkdir -p ~/notebooks
sudo systemctl daemon-reload
sudo systemctl enable jupyter
sudo systemctl start jupyter
sudo systemctl status jupyter
View real-time logs with:
sudo journalctl -u jupyter -f
Step 9: Configure Nginx as a Reverse Proxy for Jupyter
Proxying Jupyter through Nginx on port 80 or 443 is the recommended setup because it allows you to use a proper domain name, manage SSL certificates centrally, and avoid exposing port 8888 to the internet.
sudo tee /etc/nginx/conf.d/jupyter.conf <<'EOF'
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name yourdomain.com;
location /jupyter/ {
proxy_pass http://127.0.0.1:8888/jupyter/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support — required for Jupyter kernel communication
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
}
}
EOF
The WebSocket proxy headers are critical — Jupyter uses WebSockets for live two-way communication between the browser and the Python kernel. Without them, code execution will fail silently.
sudo nginx -t
sudo systemctl reload nginx
Step 10: Open Firewall Ports
Allow HTTP and HTTPS traffic through firewalld:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
If you are running Jupyter directly on port 8888 without Nginx, open that port instead:
sudo firewall-cmd --permanent --add-port=8888/tcp
sudo firewall-cmd --reload
Step 11: Access Jupyter Notebook
Open a web browser and navigate to:
http://yourdomain.com/jupyter/
You will be prompted to enter the password you configured in Step 5. After authentication, you will see the Jupyter file browser where you can create new notebooks or open existing ones.
Jupyter Notebook is now fully deployed on RHEL 7 with password authentication, a systemd service for automatic startup, and an Nginx reverse proxy for clean URL access. The configuration discussed here provides a solid foundation for data science work on a shared server. For multi-user environments, consider JupyterHub, which provides user-level authentication and isolated notebook servers for each user. Always ensure your server is kept up to date with security patches, especially when Jupyter is internet-accessible, as notebook servers that execute arbitrary code are high-value targets for attackers.