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

  1. Install Unit with the unit-dev/unit-devel package. Next, install Unit’s unit-http package:

    # npm install -g --unsafe-perm unit-http
  2. Create your app directory, install Koa, and link unit-http:

    $ mkdir -p /path/to/app/
    $ cd /path/to/app/
    $ npm install koa
    # npm link unit-http
  3. Let’s try a version of the tutorial app, saving it as /path/to/app/app.js:

    const Koa = require('koa');
    const app = new Koa();
    // logger
    app.use(async (ctx, next) => {
      await next();
      const rt = ctx.response.get('X-Response-Time');
      console.log(`${ctx.method} ${ctx.url} - ${rt}`);
    // x-response-time
    app.use(async (ctx, next) => {
      const start =;
      await next();
      const ms = - start;
      ctx.set('X-Response-Time', `${ms}ms`);
    // response
    app.use(async ctx => {
      ctx.body = 'Hello, Koa on Unit!';

    The file should be made executable so the application can run on Unit:

    $ chmod +x app.js
  4. Run the following command so Unit can access the application directory:

    # chown -R unit:unit /path/to/app/


    The unit:unit user-group pair is available only with official packages, Docker images, and some third-party repos. Otherwise, account names may differ; run the ps aux | grep unitd command to be sure.

    For further details, including permissions, see the security checklist.

  5. Next, prepare the Koa configuration for Unit:

        "listeners": {
            "*:80": {
                "pass": "applications/koa"
        "applications": {
            "koa": {
                "type": "external",
                "working_directory": "/path/to/app/",
                "executable": "/usr/bin/env",
                "arguments": [
  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 -h 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 -v
          *   Trying
          * TCP_NODELAY set
          * Connected to localhost ( port 80 (#0)
          > GET / HTTP/1.1
          > Host: localhost
          > User-Agent: curl/7.68.0
          > Accept: */*
          * Mark bundle as not supporting multiuse
          < HTTP/1.1 200 OK
          < Content-Type: text/plain; charset=utf-8
          < Content-Length: 11
          < X-Response-Time: 0ms
          < Server: Unit/1.32.1
          Hello, Koa on Unit!