Docs Developer Tools Runtime Apps

Runtime Applications

Deploy and manage Node.js, Python, Ruby, .NET, and Docker applications alongside your PHP websites.

Overview

Runtime apps let you run long-running processes (web servers, APIs, workers) on a domain. When you create a runtime app, Pinkerver:

  1. Allocates a unique port (10000-60000 range)
  2. Creates a systemd service unit (pinkerver-rt-{id}.service)
  3. Configures NGINX as a reverse proxy from the domain to 127.0.0.1:{port}
  4. Writes an environment file with your custom vars + PORT

Traffic Flow

Client NGINX :80/:443 127.0.0.1:{port} Your App

Installing Runtime Versions

Before creating apps, install the runtime versions you need. Go to Runtime Versions in the sidebar.

Click Install on any version to begin. A progress dialog shows real-time installation output. Installations run in the background and typically take 1-3 minutes.

Runtime Available Versions Package Source
Node.js18, 20, 22 (LTS)NodeSource APT repository
Python2.7, 3.10-3.13System APT + deadsnakes PPA
Ruby3.1, 3.2, 3.3System APT or ruby-install
.NET6.0, 8.0, 9.0Microsoft APT repository
DockerlatestDocker official APT repository

Node.js

FieldDescriptionExample
Entry PointMain JS file to executeapp.js
Process Modefork (single) or cluster (multi via PM2)fork
InstancesNumber of cluster workers (cluster mode only)2

Fork mode runs your app with node {entry_point}. Your app must listen on the PORT environment variable:

// app.js
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => res.send('Hello World'));
app.listen(port, '127.0.0.1', () => {
  console.log(`Listening on port ${port}`);
});

Cluster mode uses PM2 runtime: npx pm2-runtime start {entry_point} -i {instances}. Your app code stays the same — PM2 handles the forking.

Tip: Run npm install in your domain's document root before starting the app.

Python

FieldDescriptionExample
Entry PointWSGI/ASGI module pathapp:app
Servergunicorn (WSGI) or uvicorn (ASGI)gunicorn
WorkersNumber of worker processes2

A Python virtual environment (.venv) is automatically created in the app root with the selected server installed.

Flask Example

# app.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello World'

Entry point: app:app

FastAPI Example

# main.py
from fastapi import FastAPI
app = FastAPI()

@app.get('/')
def read_root():
    return {'message': 'Hello World'}

Entry point: main:app, Server: uvicorn

Tip: Install your dependencies inside the venv: .venv/bin/pip install -r requirements.txt

Python 2.7 Legacy

Python 2.7 is available for legacy applications that haven't been migrated to Python 3. It is marked with a Legacy badge in the version list.

Key differences from Python 3.x:

  • No virtual environment is created (Python 2 lacks the venv module)
  • Dependencies must be installed system-wide or managed manually with virtualenv
Warning: Python 2.7 reached end-of-life in January 2020 and no longer receives security updates. Use it only for applications that cannot be migrated to Python 3.

Ruby

FieldDescriptionExample
Entry PointRack config fileconfig.ru
Serverpuma or passengerpuma
WorkersNumber of worker processes2

Sinatra Example

# config.ru
require 'sinatra'

get '/' do
  'Hello World'
end

run Sinatra::Application
Tip: Run bundle install in the document root before starting the app.

.NET

FieldDescriptionExample
Entry PointCompiled DLL to runMyApp.dll

The startup command runs: dotnet {entry_point} --urls http://127.0.0.1:$PORT

Building & Deploying

  1. On your development machine, publish your app:
    dotnet publish -c Release -o ./publish
  2. Upload the publish/ folder contents to your domain's document root
  3. Set the entry point to your main DLL (e.g., MyApp.dll)

Minimal API Example

// Program.cs
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World");

app.Run();
Tip: .NET apps bind to the URL specified by --urls, which Pinkerver sets automatically. You don't need to configure Kestrel URLs in your app.

Docker

FieldDescriptionExample
Docker ImageImage name with optional tagnginx:latest

The container must listen on $PORT internally.

Tip: Make sure Docker is installed from the Runtime Versions page before creating Docker apps.

Managing Apps

ActionDescription
StartStarts the systemd service
StopStops the service gracefully
RestartRestarts the service (useful after code changes)
EditChange name, entry point, env vars, server settings
LogsView recent stdout/stderr output
DeleteStops service, removes NGINX proxy, deletes all config

Status Indicators

Running Stopped Starting Error

Environment Variables

Add custom environment variables in the create/edit form. These are written to /etc/pinkerver/runtime-env/{id}.env and loaded by systemd.

The PORT variable is always set automatically — do not override it.

NODE_ENV=production
DATABASE_URL=mysql://user:pass@localhost/mydb
SECRET_KEY=your-secret-here

Changes to environment variables take effect after restarting the app.

Logs

Click the terminal icon on any runtime app to view logs. Logs auto-refresh every 3 seconds. The last 200 lines are shown by default.

For more detailed debugging via SSH:

journalctl -u pinkerver-rt-{id} -f

© 2026 Pinkerver. All rights reserved.