Run JupyterLab on the VPS loopback address, then forward that private port to your computer with OpenSSH. The complete pattern is:
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
jupyter lab --no-browser --ip=127.0.0.1 --port=8888
ssh -N -L 8888:127.0.0.1:8888 USER@VPS_HOST
Keep the Jupyter process and the SSH tunnel running, open the forwarded address in your local browser, and enter the token printed by Jupyter. Nothing requires port 8888 to be exposed to the public internet.
As an Amazon Associate I earn from qualifying purchases.
What this setup does
A VPS gives you a remote Linux machine with its own CPU, memory, storage and network connection. Jupyter runs there, so notebooks use the VPS environment and continue to access files and data stored on that machine. Your browser remains on your laptop or desktop.
The secure arrangement has two separate connections:
#1 Best Overall
- Jupyter listens on
127.0.0.1on the VPS. That loopback address is reachable from the VPS itself, not directly from the internet. - SSH creates a local listening port on your computer and carries its traffic through the encrypted SSH connection to the VPS loopback port.
This is an SSH-only, single-user pattern. It avoids a public firewall rule for the notebook port, but it does not replace Jupyter authentication. The token or password still protects the web application after the tunnel is established.
Requirements and decisions before you begin
VPS and account
Use a Linux VPS that you can reach with SSH. Record its public hostname or IP address, the SSH username, and the SSH key or other credential required by your provider. Work as a normal, dedicated user with only the permissions needed for the project. Avoid running Jupyter as root unless a deployment specifically requires it.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Local computer
Your local computer needs an SSH client and a web browser. OpenSSH is available by default on most Linux and macOS systems and can be installed or enabled on current Windows systems. The local computer does not need Python or Jupyter for this tunnel method.
Port choices
Port 8888 is a common example and Jupyter’s usual default, not a requirement. You need one free port on the VPS and one free port on your computer. They may be different: the first number in the SSH -L expression is local, while the last number is the remote Jupyter port.
Choose the operating model
Decide whether this is an interactive session that you start and stop manually or a longer-lived service. Manual operation is easiest for one person and occasional work. A persistent service needs a service manager, restart policy, logging and a plan for updates; those are operational choices beyond the basic tunnel.
Log in and prepare the VPS
- From your local terminal, connect with the credentials supplied for the VPS:
ssh USER@VPS_HOSTReplace
USERandVPS_HOSTwith your actual account and hostname or address. If your SSH key uses a non-default filename, add the appropriate identity option. - Confirm that you are using the intended non-root account. Keep project files and the Python environment owned by that account.
- Update the project directory and select the Python environment you intend to use. A separate environment prevents notebook packages from changing the operating system’s Python installation.
If you already have a project environment, activate it before installing JupyterLab. If not, create one using the environment manager your project supports. The important requirement is that the environment containing JupyterLab is active when you launch the server.
Free tools Windows power users keep installed
One-click scans. No signup required.
Install JupyterLab in the project environment
Project Jupyter documents three common installation routes: conda, mamba and pip. Pick one; do not install the same application into several environments unless you have a specific reason.
| Route | Typical command | When it fits |
|---|---|---|
| conda |
|
Projects already managed with conda environments and packages. |
| mamba |
|
Conda-compatible environments where you prefer mamba’s package solver. |
| pip |
|
A standard Python virtual environment or a project that uses pip requirements. |
After installation, verify that the command resolves inside the active environment:
Rank #2
which jupyter
jupyter lab --version
The first command should point to the environment you selected. If it points to a system location, activate the environment again or invoke Jupyter through that environment’s Python installation.
Start Jupyter privately on the VPS
Launch Jupyter without attempting to open a browser on the headless VPS:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
jupyter lab --no-browser --ip=127.0.0.1 --port=8888
--no-browser prevents a graphical browser launch. --ip=127.0.0.1 binds the server to the VPS loopback interface. --port=8888 selects the remote listening port; replace it if another process already uses 8888.
Jupyter prints a URL containing an authentication token in the VPS terminal. Leave this terminal session running. Copy the complete URL somewhere private, or copy only the token and use the local URL after creating the tunnel.
If port 8888 is occupied
The startup output will identify the port Jupyter actually uses or report that the requested port is unavailable. You can stop the conflicting process and restart on 8888, or choose another explicit remote port:
jupyter lab --no-browser --ip=127.0.0.1 --port=8899
Whatever remote port you choose must be the final number in the SSH forwarding command. Do not assume that changing the local browser port changes the port on the VPS.
Recommended Free Tools
Authentication is still required
Jupyter Server generates a token by default. Keep token or password authentication enabled. Configuring an empty token disables authentication altogether and is explicitly not recommended. A private SSH tunnel limits network exposure, but anyone who gains access to your local browser session or the forwarded port could still reach the web application, so retain Jupyter’s own authentication.
Create the SSH tunnel from your computer
Open a second local terminal; do not run this command in the VPS terminal where Jupyter is running. For a VPS Jupyter process on port 8888, use:
ssh -N -L 8888:127.0.0.1:8888 USER@VPS_HOST
OpenSSH’s -L option creates local forwarding. In local_port:destination_host:remote_port, the first port is opened on your computer, the destination host is evaluated from the VPS side of the connection, and the final port is the Jupyter listener on the VPS. 127.0.0.1 as the destination deliberately targets the VPS loopback interface. -N tells SSH not to start a remote shell; this terminal is used only to carry the tunnel.
Use a different local port
If another local application already listens on 8888, keep Jupyter on the VPS at 8888 and select a free local port, such as 8890:
ssh -N -L 8890:127.0.0.1:8888 USER@VPS_HOST
In that case, browse to http://127.0.0.1:8890. The local and remote numbers do not need to match.
Use a different remote port
If Jupyter is listening on 8899 on the VPS and local 8888 is free, forward it with:
ssh -N -L 8888:127.0.0.1:8899 USER@VPS_HOST
Use the local address http://127.0.0.1:8888 in your browser. If both sides differ, make both changes explicit so that you can diagnose each end independently.
Keep the listener local
Use an explicit localhost address in the forwarding expression. Binding the local listener to localhost keeps the forwarded port for local use only instead of advertising it on other network interfaces. The browser address should likewise remain 127.0.0.1, not the VPS’s public hostname.
Open Jupyter and work normally
- Leave the tunnel terminal running. Closing it closes the forwarding connection.
- Open the matching local URL in your browser:
http://127.0.0.1:8888for the first command, or the alternate local port you selected. - Paste the token from the VPS Jupyter output when prompted. If you copied the full token-bearing URL, you can open that URL through the local forwarded address after checking that its port matches your local listener.
- Use JupyterLab as usual. Kernels, files and installed libraries are on the VPS, not on the local computer.
The browser-to-localhost leg and the SSH connection must both remain available. A browser refresh cannot repair a stopped Jupyter process or a closed SSH tunnel.
Stop the session cleanly
- Save notebooks and stop active kernels from JupyterLab.
- In the local tunnel terminal, press
Ctrl-C. This closes the SSH forwarding process. - In the VPS terminal running Jupyter, press
Ctrl-Cand confirm the shutdown if Jupyter asks. This stops the server process.
If you need the server to survive a disconnected shell, configure an intentional service-manager or session-management solution and document its restart, logging and authentication settings. A manually launched process should not be assumed to persist after its controlling session ends.
Security controls that matter
Keep Jupyter on loopback for SSH-only access
Binding to 127.0.0.1 means the notebook port is not directly reachable through the VPS’s public interfaces. Binding to 0.0.0.0 or a public address changes the exposure model: the port may become reachable from networks allowed by routing and firewall rules. Use that only when you deliberately configure firewall policy, authentication and encrypted web access.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallProtect the token and any password
Do not paste a live token into a public issue tracker, shell transcript, screenshot or shared chat. Treat it like a credential. If you believe it has leaked, stop the server and restart it so a new token is generated, or set a deliberate password-based configuration according to Jupyter’s documentation.
Use least privilege
Run the server as the dedicated project user, keep file permissions appropriate to that user, and avoid granting notebook code unnecessary operating-system privileges. A notebook can execute arbitrary Python and shell commands available to its account, so the account boundary is meaningful.
If you publish Jupyter directly
A public deployment is a different architecture, not a minor variation of this tunnel. Use HTTPS and authentication when publishing a notebook server. Official guidance for public servers states that an SSL deployment should always be accessed with an https:// URL. You also need deliberate firewall rules, certificate management, hostname handling and an access-control plan.
Troubleshoot by separating the three endpoints
There are three points to check: the browser’s local port, the SSH listener and the VPS Jupyter process. Test them in that order.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesBrowser refuses the connection
- Confirm that the Jupyter terminal is still running and has not exited.
- Check that the browser port is the first number in
-L. For-L 8890:127.0.0.1:8888, the browser address ishttp://127.0.0.1:8890. - Make sure the tunnel terminal is still connected and has not been interrupted.
SSH reports that the local port is busy
Choose another unused local port, such as 8890, and browse to that port:
ssh -N -L 8890:127.0.0.1:8888 USER@VPS_HOST
Do not change the final number unless the VPS Jupyter process also moved.
Jupyter prints a different port
Either stop the conflicting process and restart Jupyter on your planned remote port, or forward the port Jupyter actually selected. The final number in -L must equal the VPS listening port.
Best Value
HTTP 403 or a host-header error
Keep the browser URL on 127.0.0.1. Review Jupyter’s allow_remote_access setting only when you intentionally use a reverse proxy or a non-local hostname. Changing that setting is not a substitute for correcting a tunnel that points to the wrong address.
The tunnel connects but the page hangs
- Verify that Jupyter is listening on the VPS loopback address and the expected remote port.
- Check that the SSH account can reach that loopback address and port.
- Confirm that the tunnel’s destination address is
127.0.0.1on the VPS side, not an address that exists only on your local computer.
The connection drops
Run the tunnel with verbose SSH logging to observe negotiation and forwarding errors:
ssh -v -N -L 8888:127.0.0.1:8888 USER@VPS_HOST
Inspect the actual log and the VPS’s resource limits before changing settings. A dropped tunnel can result from network interruption, an SSH timeout, a stopped Jupyter process or resource exhaustion; the verbose output distinguishes these cases better than guessing.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Compare deployment choices before exposing anything
The SSH tunnel is usually the smallest security and operations footprint for one person. A direct public deployment can be convenient for a team or an automated service, but it adds responsibilities that the tunnel avoids.
| Deployment | Exposure | Authentication | Persistence | Audience | Operational burden |
|---|---|---|---|---|---|
| Localhost plus SSH tunnel | Jupyter port stays on VPS loopback; SSH is the entry point. | SSH access plus Jupyter token or password. | Usually a manually started process unless you add a service manager. | Single user or one controlled operator. | Low; maintain the VPS, Python environment and SSH access. |
| Public Jupyter behind HTTPS | Web service is reachable through a public hostname and firewall path. | Jupyter authentication plus the access controls you configure; SSO may be appropriate for an organization. | Normally managed as a service with restart and logging policies. | Selected external or organizational users. | Higher; firewall, TLS certificates, proxy headers, updates and account management are your responsibility. |
| Multi-user platform | Designed around an application gateway rather than one personal listener. | Centralized user authentication and per-user sessions. | Managed centrally with lifecycle and resource policies. | Teams and classes. | Highest initial setup, but clearer separation than sharing one personal server. |
Jupyter’s documentation distinguishes a personal notebook server from a multi-user server. If several people need accounts, isolated kernels or shared administration, evaluate JupyterHub or another managed architecture instead of handing one user’s token to a group.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Choose a VPS with the right practical characteristics
No single VPS size or provider is required by this workflow. Select based on the notebooks you will run and where your users are located. Compare:
- CPU and RAM for the kernels and data-processing jobs you expect to execute.
- Storage type and capacity for environments, datasets, checkpoints and notebook outputs.
- Region and network latency between the VPS and your normal working location.
- Bandwidth limits and transfer pricing if notebooks move large datasets.
- Snapshot and backup facilities so you can recover the environment and project files.
- IPv4 and IPv6 availability, SSH key support and the provider’s recovery console.
- Support and maintenance expectations, especially if the server will run continuously.
These are infrastructure decisions, not reasons to expose port 8888. The tunnel works over the SSH access you already secure, regardless of which VPS host supplies the machine.
End-to-end checklist
- Linux VPS provisioned and reachable by SSH.
- Dedicated non-root user selected.
- Project Python environment created or activated.
- JupyterLab installed with conda, mamba or pip.
- Jupyter started with
--no-browser --ip=127.0.0.1and a known remote port. - Token copied privately from the VPS terminal.
- Local SSH forwarding command uses a free local port and the actual remote port.
- Browser opened at the local
127.0.0.1address. - SSH tunnel kept open while working.
- Jupyter and the tunnel stopped deliberately when finished.
Bottom line
For a personal Jupyter workload on a VPS, bind Jupyter to the VPS loopback address and reach it through an SSH local-forward tunnel. This keeps the notebook port off the public internet while preserving Jupyter’s token or password protection. Change only the local forwarding port when your computer has a conflict; change the remote forwarding port only when Jupyter is listening elsewhere. If your audience grows beyond one controlled user, move to an HTTPS-protected, managed multi-user design rather than sharing a personal notebook server.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

