v. 1.21.0


To run apps built with the Starlette web framework using Unit:

  1. Install Unit with a Python 3.5+ language module.

  2. Create a virtual environment to install Starlette’s PIP package:

    $ cd /path/to/app/
    $ python3 --version
          Python 3.x.y
    $ python3 -m venv venv
    $ source venv/bin/activate
    $ pip install starlette[full]
    $ deactivate


    Create your virtual environment with a Python version that matches the language module from Step 1 up to the minor number (3.x in this example). Also, the app type in Step 5 must resolve to a similarly matching version; Unit doesn’t infer it from the environment.

  3. Let’s try a version of a tutorial app, saving it as /path/to/app/

    from starlette.applications import Starlette
    from starlette.responses import PlainTextResponse
    from starlette.routing import Route, Mount, WebSocketRoute
    def homepage(request):
        return PlainTextResponse('Hello, world!')
    def user_me(request):
        username = "John Doe"
        return PlainTextResponse('Hello, %s!' % username)
    def user(request):
        username = request.path_params['username']
        return PlainTextResponse('Hello, %s!' % username)
    async def websocket_endpoint(websocket):
        await websocket.accept()
        await websocket.send_text('Hello, websocket!')
        await websocket.close()
    def startup():
        print('Ready to go')
    routes = [
        Route('/', homepage),
        Route('/user/me', user_me),
        Route('/user/{username}', user),
        WebSocketRoute('/ws', websocket_endpoint)
    app = Starlette(debug=True, routes=routes, on_startup=[startup])


    This sample omits the static route because Unit’s quite capable of serving static files itself if needed.

  4. Set installation path permissions to secure access, for example:

    # chown -R app_user:app_group /path/to/app/

    Update the placeholders above with actual values, noting them for later use in Unit configuration.

  5. Next, put together the Starlette configuration for Unit, adding a route to serve static content:

        "listeners": {
            "*:80": {
                "pass": "routes"
        "routes": [
                "match": {
                    "uri": "/static/*"
                "action": {
                    "share": "/path/to/app/"
                "action": {
                    "pass": "applications/starlette"
        "applications": {
            "starlette": {
                "type": "python 3.x",
                "user": "app_user",
                "group": "app_group",
                "path": "/path/to/app/",
                "home": "/path/to/app/venv/",
                "module": "asgi",
                "callable": "app"
  6. Upload the updated configuration. Assuming the JSON above was added to config.json:

    # curl -X PUT --data-binary @config.json --unix-socket \
           /path/to/control.unit.sock http://localhost/config/


    The control socket path may vary; run unitd --help or see Startup and Shutdown for details.

    After a successful update, your app should be available on the listener’s IP address and port:

    $ curl http://localhost
          Hello, world!
    $ curl http://localhost/user/me
          Hello, John Doe!
    $ wscat -c ws://localhost/ws
          Connected (press CTRL+C to quit)
          < Hello, websocket!
          Disconnected (code: 1000, reason: "")