Skip to content

airbase.json

Complete specification of airbase.json format

This reference provides the complete specification for the airbase.json configuration file used by Airbase CLI for container deployments.


Overview

The airbase.json file contains project configuration for deploying containers to Airbase.

Optional but Recommended

While you can deploy without airbase.json using the --project flag with the deploy command, we strongly encourage using airbase configure to create this file. This approach:

  • Reduces risk of malformed or invalid JSON
  • Provides a consistent configuration across deployments
  • Makes project setup explicit and documented
  • Is safe to commit to your repository (contains no secrets or sensitive information)

Purpose: - Identifies your project (handle) - Specifies application port - Configures instance size - Sets deployment framework - Controls IP access restrictions (whitelisting)

Alternative: You can deploy without airbase.json by using CLI flags:

airbase container deploy --yes --project team/project --port 3000

However, this approach requires specifying project details on every deployment and increases the risk of configuration errors.


File Location

project-root/
├── airbase.json     ← Recommended location (project root)
├── Dockerfile
├── .env
└── src/

The CLI reads this file from the current working directory when deploying.


Complete Specification

Required Fields

Field Type Description
framework string Must be "container" for container deployments
handle string Project identifier in format team-name/project-name
port number Port your application listens on inside the container

Optional Fields

Field Type Description Default
instanceType string Instance size (nano, b.small) "nano"
allowIPAddresses array List of IP addresses/CIDR ranges allowed to access the application [] (no restrictions)

Field Specifications

framework (required)

Type: string

Value: Must be "container"

Description: Specifies the deployment framework. For container-based deployments, this must always be "container".

Example:

{
  "framework": "container"
}

Validation: - Must be present - Must be exactly "container" (lowercase)

Errors:

Error: framework must be "container"

handle (required)

Type: string

Format: team-name/project-name

Description: Your project identifier from Airbase Console. This determines: - Where your application is deployed - The base URL for your application - Access permissions

Example:

{
  "handle": "runtime/demo"
}

Format rules: - Must contain exactly one forward slash (/) - Team name and project name must be lowercase - Alphanumeric characters and hyphens only - No spaces or special characters

Valid examples: - runtime/demo - my-team/my-project - govtech/payment-service

Invalid examples: - Demo (no team name) - runtime/Demo (uppercase not allowed) - runtime demo (space not allowed) - runtime/my_project (underscore not allowed)

Finding your handle:

  1. Log in to Airbase Console at https://console.airbase.tech.gov.sg
  2. Navigate to your project
  3. Copy the project handle from the project details

Errors:

Error: handle must be in format "team-name/project-name"
Error: Project not found

port (required)

Type: number

Range: 1-65535

Description: The port your application listens on inside the container. This must match the port your application code binds to.

Example:

{
  "port": 3000
}

Common ports: - 3000 - Node.js applications (Express, Next.js) - 5000 - Flask applications - 8000 - FastAPI, Django applications - 8080 - Alternative HTTP port

Important: - This is the container-internal port - External access is always via HTTPS (port 443) - Your application must read process.env.PORT (or equivalent) to respect this value - Airbase injects the PORT environment variable matching this value at runtime

Application code must listen on this port:

Node.js:

const port = process.env.PORT || 3000;  // Matches airbase.json
app.listen(port, '0.0.0.0');

Python:

import os
port = int(os.environ.get('PORT', 3000))  # Matches airbase.json
app.run(host='0.0.0.0', port=port)

Validation: - Must be a number - Must be between 1 and 65535 - Must be an integer (no decimals)

Errors:

Error: port must be a number
Error: port must be between 1 and 65535

instanceType (optional)

Type: string

Default: "nano"

Description: The instance size/compute resources for your container.

Available instance types:

Instance Type vCPU Memory Ephemeral Storage Use Case
nano 0.25 500 MB 500 MB Small apps, static sites, low traffic
b.small 0.5 1 GB 500 MB Standard web apps, APIs

Future Instance Types

Additional instance types will be introduced at a later stage as we learn more about the workloads our users are bringing to the platform. In the meantime, our goal is to keep workloads small to better manage growing infrastructure costs.

Example:

{
  "instanceType": "nano"
}

Choosing instance type:

  • Start with nano for most applications
  • Upgrade to b.small if you experience:
  • Out of memory errors
  • Slow performance
  • High CPU usage
  • Downgrade if resources are underutilized

When to use each type:

nano (default): - Static websites - Low-traffic APIs - Microservices - Single-user tools - Simple applications

b.small: - Standard web applications - REST APIs with moderate traffic - Team collaboration tools - Data visualization dashboards - Applications with database connections

Validation: - Must be one of: nano, b.small - Case-sensitive (must be lowercase)

Errors:

Error: instanceType must be one of: nano, b.small

Cost implications:

Larger instances may have cost implications. Check with your organization's Airbase administrator.


allowIPAddresses (optional)

Type: array of strings

Default: [] (no restrictions - all IPs allowed)

Description: List of IP addresses or CIDR ranges that are allowed to access your application. When specified, only requests from these IPs will be permitted.

Not Environment-Specific

Unlike .env files, IP whitelisting in airbase.json is not environment-specific. The whitelist applies to whichever environment you deploy to at the time of deployment.

To have different whitelists for different environments, you need to: - Use different airbase.json files managed in different git branches, OR - Manually edit airbase.json before each deployment

Example:

{
  "allowIPAddresses": [
    "8.29.230.18/31",
    "104.30.161.22/31",
    "104.30.161.24/31"
  ]
}

Supported formats: - Single IP (IPv4): "203.0.113.42" - Single IP (IPv6): "2001:db8::1" - CIDR range (IPv4): "203.0.113.0/24" - CIDR range (IPv6): "2001:db8::/32"

Validation: - Must be an array (empty array [] is valid) - Each entry must be a valid IP address or CIDR range - Invalid entries will cause deployment to fail

Errors:

Error: Invalid allowIPAddresses entry: "not-an-ip"
Error: allowIPAddresses must be an array

Use cases: - Restrict access to internal government networks - Limit application to specific office IP ranges - Create private applications accessible only from VPN - Control access for staging/testing environments

Updating whitelist without rebuilding:

You can update the IP whitelist without rebuilding your container:

# 1. Edit airbase.json to update whitelist
vim airbase.json

# 2. Run airbase configure (optional - to validate)
airbase configure

# 3. Deploy to update whitelist
airbase container deploy --yes staging

The whitelist settings are applied at deployment time to the target environment.

Branch-based whitelist management:

For managing different whitelists per environment using git branches:

# main branch - production whitelist
git checkout main
# airbase.json contains production IPs
airbase container deploy --yes

# staging branch - staging whitelist
git checkout staging
# airbase.json contains staging/testing IPs
airbase container deploy --yes staging

Example configurations:

Open access (no restrictions):

{
  "framework": "container",
  "handle": "team/project",
  "port": 3000,
  "allowIPAddresses": []
}

Restricted to government network:

{
  "framework": "container",
  "handle": "team/project",
  "port": 3000,
  "allowIPAddresses": [
    "192.168.0.0/16",
    "10.0.0.0/8"
  ]
}

Restricted to specific offices:

{
  "framework": "container",
  "handle": "team/project",
  "port": 3000,
  "allowIPAddresses": [
    "203.0.113.0/24",
    "198.51.100.0/24",
    "2001:db8:abcd::/48"
  ]
}


Complete Examples

Minimal Configuration

{
  "framework": "container",
  "handle": "runtime/demo",
  "port": 3000
}

This is the minimum required configuration. Uses default nano instance type.

Full Configuration

{
  "framework": "container",
  "handle": "runtime/demo",
  "port": 3000,
  "instanceType": "b.small",
  "allowIPAddresses": [
    "8.29.230.18/31",
    "104.30.161.22/31",
    "104.30.161.24/31"
  ]
}

Specifies all available fields including IP whitelisting.

Node.js Application

{
  "framework": "container",
  "handle": "my-team/api-service",
  "port": 3000,
  "instanceType": "nano"
}

Python Flask Application

{
  "framework": "container",
  "handle": "data-team/analytics-api",
  "port": 5000,
  "instanceType": "b.small"
}

Python FastAPI Application

{
  "framework": "container",
  "handle": "backend-team/user-service",
  "port": 8000,
  "instanceType": "b.small"
}

Static Site (Nginx)

{
  "framework": "container",
  "handle": "frontend-team/company-website",
  "port": 3000,
  "instanceType": "nano"
}

Note: Even though Nginx listens on port 8080 internally, specify 3000 in airbase.json as the configured port.


Creating airbase.json

Use the CLI's interactive tool:

airbase configure

This will prompt you for: 1. Project handle (from your available projects) 2. Port (default: 3000) 3. IP address whitelisting (optional)

Then creates airbase.json automatically.

Note: The airbase configure command does not prompt for instance type. The generated file will use the default nano instance type. To use a different instance type, edit the airbase.json file after creation and add "instanceType": "b.small" (or your desired type).

Method 2: Manual Creation

Create the file manually:

# Create file
cat > airbase.json << 'EOF'
{
  "framework": "container",
  "handle": "team/project",
  "port": 3000
}
EOF

Replace team/project with your actual project handle.

Method 3: Copy from Template

  1. Create airbase.json in your project root
  2. Copy this template:
{
  "framework": "container",
  "handle": "your-team/your-project",
  "port": 3000,
  "instanceType": "nano"
}
  1. Update values for your project

Validation

CLI Validation

The CLI validates airbase.json when you deploy:

airbase container deploy --yes

Validation checks: - File exists - Valid JSON syntax - All required fields present - Field values are correct types - Project handle exists in Airbase - Instance type is valid

Manual Validation

Check JSON syntax:

# On macOS/Linux
cat airbase.json | python3 -m json.tool

# Output should be formatted JSON

If syntax is invalid, you'll see an error message.


Common Issues

Issue 1: File Not Found

Error:

Error: airbase.json not found

Cause: File doesn't exist in current directory or has wrong name.

Solution:

# Check if file exists
ls -la airbase.json

# Create file if missing
airbase configure

Issue 2: Invalid JSON Syntax

Error:

Error: Failed to parse airbase.json: Unexpected token

Cause: JSON syntax error (missing comma, quote, bracket, etc.)

Solution:

  • Check for:
  • Missing commas between fields
  • Missing quotes around strings
  • Trailing commas (not allowed in JSON)
  • Incorrect brackets

Common mistakes:

{
  "framework": "container",
  "handle": "team/project"   Missing comma
  "port": 3000,              Syntax error above
  "instanceType": "nano",    Trailing comma not allowed
}

Correct:

{
  "framework": "container",
  "handle": "team/project",
  "port": 3000,
  "instanceType": "nano"
}

Issue 3: Project Not Found

Error:

Error: Project not found: team/project

Cause: Project handle doesn't exist in Airbase or you don't have access.

Solution:

  1. Log in to Airbase Console
  2. Verify project handle
  3. Check you have access to the project
  4. Update airbase.json with correct handle

Issue 4: Port Mismatch

Problem: Application deployed but not accessible.

Cause: Port in airbase.json doesn't match port application listens on.

Solution:

Ensure consistency:

airbase.json:

{
  "port": 3000
}

Application code (Node.js):

const port = process.env.PORT || 3000;  // Must match
app.listen(port, '0.0.0.0');

Application code (Python):

port = int(os.environ.get('PORT', 3000))  # Must match
app.run(host='0.0.0.0', port=port)

Issue 5: Wrong Instance Type

Error:

Error: Invalid instanceType: large

Cause: Instance type value is incorrect.

Solution: Use one of the valid types: - nano - b.small

Note: Exact spelling and case-sensitive.


Updating Configuration

Changing Instance Type

  1. Edit airbase.json:
{
  "framework": "container",
  "handle": "team/project",
  "port": 3000,
  "instanceType": "b.small"   Changed from nano
}
  1. Redeploy:
airbase container deploy --yes

The new instance type takes effect immediately.

Changing Port

Important: Changing the port requires:

  1. Update airbase.json
  2. Update application code to listen on new port
  3. Rebuild and redeploy
airbase container build
airbase container deploy --yes

Changing Project Handle

Not recommended. If you need to change project handle:

  1. Create new project in Airbase Console
  2. Update airbase.json with new handle
  3. Deploy to new project
  4. Undeploy from old project

Version Control

Git Configuration

Always commit airbase.json:

git add airbase.json
git commit -m "Add Airbase configuration"

airbase.json is safe to commit to your repository because it contains only non-sensitive configuration: - Project handle (public identifier) - Port number (not a secret) - Instance type (resource allocation) - Framework type (deployment method)

Do NOT commit secrets:

# .gitignore
.env
.env.*

Secrets like database URLs, API keys, and passwords should only be in .env files (which are gitignored).

Example Repository Structure

project-root/
├── .gitignore           ← Ignore .env files
├── airbase.json         ← Commit this
├── Dockerfile           ← Commit this
├── .env                 ← Do NOT commit (in .gitignore)
├── .env.staging         ← Do NOT commit (in .gitignore)
└── src/

CLI Overrides

You can override airbase.json values via CLI flags:

# Override port
airbase container deploy --yes --port 8080

# Override instance type
airbase container deploy --yes --instance-type b.small

# Override project
airbase container deploy --yes --project team/different-project

Use case: Testing different configurations without editing file.


Schema Reference

JSON Schema

For tools that support JSON Schema validation:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["framework", "handle", "port"],
  "properties": {
    "framework": {
      "type": "string",
      "const": "container"
    },
    "handle": {
      "type": "string",
      "pattern": "^[a-z0-9-]+/[a-z0-9-]+$"
    },
    "port": {
      "type": "integer",
      "minimum": 1,
      "maximum": 65535
    },
    "instanceType": {
      "type": "string",
      "enum": ["nano", "b.small"],
      "default": "nano"
    },
    "allowIPAddresses": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "default": []
    }
  },
  "additionalProperties": false
}

TypeScript Type Definition

interface AirbaseConfig {
  framework: 'container';
  handle: string;  // Format: team-name/project-name
  port: number;    // 1-65535
  instanceType?: 'nano' | 'b.small';
  allowIPAddresses?: string[];  // IP addresses or CIDR ranges
}

Best Practices

✅ Do

  • Commit airbase.json to version control
  • Use nano instance type initially
  • Keep configuration simple (only add fields you need)
  • Match port with application code
  • Use airbase configure for initial setup
  • Document instance type choices in README

❌ Don't

  • Don't include secrets (use .env files instead)
  • Don't use uppercase in handle
  • Don't use underscores in handle
  • Don't forget to rebuild after changing port
  • Don't use random ports (stick to conventions: 3000, 5000, 8000)

Environment Variables (.env)

For runtime configuration (database URLs, API keys, etc.), use .env files:

# .env
DATABASE_URL=postgresql://...
API_KEY=secret123

See Environment Variables Reference for complete details.

Dockerfile

Your Dockerfile must: - Use Airbase base images - Listen on $PORT environment variable - Run as app user

See Dockerfile Requirements for complete details.


See Also