Run a Web Server
For testing and development, it is possible to run a web server inside a CoCalc project. Only project collaborators can access it.
If you want to run an exposed web server, you can do it with Compute Servers!
Web Server Proxy
If your HTTP web server is listening on PORT
, you can access it at
https://cocalc.com/PROJECT_ID/server/PORT/
where PROJECT_ID
is your project ID like 60f9ea81-5bd0-45ae-9965-76de986e101f
, visible in the URL of your project itself and accessible via COCALC_PROJECT_ID
environment variable.
As a test, you can launch a simple server from your project as
python -m http.server 8000
Warning
Your web server must serve all IP addresses, not just localhost
!
For example, you might have to start the service using --ip=0.0.0.0
(the exact flag depends on the service).
Warning
Your web server should not rely on absolute URLs.
For example, if it serves a file index.html
like this
<a href='/index.html'>HOME!</a>
then when you click this link your browser will try to grab
https://cocalc.com/index.html
instead of
https://cocalc.com/PROJECT_ID/server/PORT/index.html
Obviously, this can’t possibly work.
Many web servers, e.g., tensorboard, work fine and do not do this. Others won’t work without modification.
Note
This functionality is similar to VS Code proxy.
Port Proxy
If you use port
instead of server
, i.e. a URL like
https://cocalc.com/PROJECT_ID/port/PORT/
your web server will get a request for /PROJECT_ID/port/PORT/
rather than for /
as it does with server
. Otherwise, everything is the same, including the warnings.
Python Example
Let’s put the following code into server.py
:
from http.server import HTTPServer, SimpleHTTPRequestHandler
import os
BASE_URL = "/" + os.environ['COCALC_PROJECT_ID'] + '/port/8000'
class BaseURLHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path.startswith(BASE_URL):
# Rewrite to strip the prefix before serving files
self.path = self.path[len(BASE_URL):] or "/"
return super().do_GET()
else:
self.send_error(404, "Not Found")
if __name__ == "__main__":
server = HTTPServer(("0.0.0.0", 8000), BaseURLHandler)
print(f"Serving on https://cocalc.com{BASE_URL}/")
server.serve_forever()
Then you can start it in a terminal and get something like
~$ python -m server
Serving on https://cocalc.com/35dd0d93-f702-4bd4-90dc-f5a3c2117ba2/port/8000/
192.168.144.61 - - [05/Oct/2025 21:43:27] "GET /35dd0d93-f702-4bd4-90dc-f5a3c2117ba2/port/8000/HW2/ HTTP/1.1" 200 -
...
Security
Only project collaborators can access the web server via an SSL encrypted connection. Our proxy server will reject all other requests. This means you don’t have to worry about setting up logins/passwords on whatever web server you run in your project. If you want to run a web server that is visible to anybody in the world, use Compute Servers!
Dynamically Generated Subdomains
Use Compute Servers!