Skip to content

Application contract

Every Kyno app needs a root-level Dockerfile. Its final process must follow four rules.

  1. Listen on 0.0.0.0.
  2. Use the PORT environment variable. Kyno currently sets it to 8080.
  3. Store persistent files under /data.
  4. Use DATABASE_URL=sqlite:////data/app.db for the provisioned SQLite database.

The app may access web and API services while it is running. Direct SMTP and cloud metadata access are blocked.

Only the final image from the root Dockerfile runs. Kyno does not start every service in a Docker Compose file or monorepo.

FROM python:3.12-slim
WORKDIR /app
COPY app.py .
CMD ["python", "app.py"]
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
body = b'{"ok":true}'
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
HTTPServer(("0.0.0.0", int(os.environ["PORT"])), Handler).serve_forever()

The application root filesystem is read-only at runtime. The /data disk is writable and persists across stop, start, and redeploy.

Do not write uploads, generated reports, or SQLite files beside the application source. Write them under /data.

Kyno injects:

  • PORT
  • DATABASE_URL
  • SMOL_APP_ID
  • Variables and secrets supplied during deployment

Variable values and all variable names must be strings. Environment changes take effect after the app restarts.