Menu

Standalone Deployment Overview

This guide explains how to deploy ApiCharge as a standalone application directly on your server or virtual machine. Standalone deployment gives you more control over the environment and allows for custom integration with your infrastructure.

Note: While standalone deployment provides more flexibility, Docker deployment is generally simpler and more consistent. Consider using Docker deployment unless you have specific requirements that necessitate a standalone installation.

Prerequisites

Installation Steps

1

Download the ApiCharge Native Binary

ApiCharge is distributed as a self-contained, native binary that doesn't require .NET runtime installation.

Early Access Program

The ApiCharge native binary is currently available through our Early Access Program. Contact our team or use your Early Access credentials to download the appropriate release for your platform.

Extraction and Permissions

After downloading, extract the archive to your application directory and set the appropriate permissions:

# Extract the downloaded archive
tar -xzf apicharge-release.tar.gz -C /opt/apicharge/app

# Make the binary executable
chmod +x /opt/apicharge/app/ApiChargePrototype

Verify the installation by running:

/opt/apicharge/app/ApiChargePrototype --version
2

Prepare Installation Directory

Create a directory where you'll place the ApiCharge native binary and its configuration files:

The ApiCharge binary requires its configuration file (appsettings.json) to be in the same directory as the executable, following standard .NET Core conventions.

The binary will automatically create any additional required directories during runtime based on your configuration settings.

3

Configure ApiCharge

Create the main configuration file appsettings.json in the /opt/apicharge/config directory:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    },
    "File": {
      "Path": "/opt/apicharge/logs/apicharge.log",
      "FileSizeLimitBytes": 10485760,
      "MaxRollingFiles": 10
    }
  },
  "GlobalSettings": {
    "UseNetwork": "Testnet",
    "ToleratedClockSkew": "00:02:00",
    "QuoteValidityDuration": "01:00:00",
    "SigningKeyEnvironmentVariable": "APICHARGE_SIGNING_KEY",
    "StellarEndpointRPC": "https://soroban-testnet.stellar.org",
    "StellarNetworkPassphraseEnvironmentVariable": "APICHARGE_NETWORK_PASSPHRASE",
    "AllowSelfSignedServerCertificates": false,
    "AllowedServerCertificateThumbprints": [],
    "AllowedServerCertificateIssuers": []
  },
  "ApiChargeQuotes": {
    "Quotes": [
      {
        "RouteId": "basic-route",
        "Duration": 3600,
        "MicroUnitPrice": 100000,
        "RateLimiters": [
          {
            "$type": "CallCount",
            "Count": 100
          },
          {
            "$type": "DataLimitDownload",
            "Bytes": 10485760
          }
        ]
      },
      {
        "RouteId": "premium-route",
        "Duration": 3600,
        "MicroUnitPrice": 500000,
        "RateLimiters": [
          {
            "$type": "CallCount",
            "Count": 1000
          },
          {
            "$type": "DataLimitDownload",
            "Bytes": 104857600
          }
        ]
      }
    ]
  },
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://0.0.0.0:5000"
      },
      "Https": {
        "Url": "https://0.0.0.0:5001",
        "Certificate": {
          "Path": "/opt/apicharge/config/certificate.pfx",
          "Password": "CERTIFICATE_PASSWORD_HERE"
        }
      }
    }
  },
  "Redis": {
    "ConnectionString": "localhost:6379,abortConnect=false,connectTimeout=5000",
    "InstanceName": "ApiCharge-"
  },
  "RateLimiterPersistence": {
    "UseRedis": true,
    "PersistenceIntervalSeconds": 30,
    "RedisExpiryMultiplier": 2
  },
  "Routes": {
    "Clusters": [
      {
        "ClusterId": "defaultCluster",
        "Destinations": [
          {
            "Address": "http://localhost:8080"
          }
        ]
      }
    ],
    "Routes": [
      {
        "RouteId": "basic-route",
        "ClusterId": "defaultCluster",
        "Match": {
          "Path": "/api/basic/{**remainder}"
        }
      },
      {
        "RouteId": "premium-route",
        "ClusterId": "defaultCluster",
        "Match": {
          "Path": "/api/premium/{**remainder}"
        }
      }
    ]
  }
}

Modify this configuration based on your specific requirements. For detailed configuration options, see the Configuration documentation.

4

Configure Environment Variables

Create an environment variables file at /opt/apicharge/scripts/env.sh:

#!/bin/bash

# Signing key (replace with your actual Stellar secret key)
export APICHARGE_SIGNING_KEY="SDH3X...YOUR_STELLAR_SECRET_KEY"

# Network passphrase
export APICHARGE_NETWORK_PASSPHRASE="Test SDF Network ; September 2015"

# Environment
export ASPNETCORE_ENVIRONMENT="Production"
export DOTNET_ENVIRONMENT="Production"

# Paths
export ASPNETCORE_CONTENTROOT="/opt/apicharge/app"
export ASPNETCORE_URLS="http://0.0.0.0:5000;https://0.0.0.0:5001"

# Certificate password if using PFX
export CERTIFICATE_PASSWORD="your_cert_password_here"

Make the script executable:

chmod +x /opt/apicharge/scripts/env.sh
Security Note: The environment file contains sensitive information. Ensure it has appropriate file permissions and is only readable by the service account running ApiCharge.
5

Set Up Stellar RPC Server

The standalone ApiCharge binary requires a separately running Stellar RPC server. You have two options:

Option 1: Connect to an existing Stellar RPC server

Update your appsettings.json to point to your Stellar RPC server:

"ApiChargeProxy": {
  "Global": {
    "StellarEndpointRPC": "http://localhost:8000",
    // Other settings...
  }
}
Option 2: Run your own Stellar RPC server

Follow the Stellar Soroban RPC documentation to set up your own RPC server. This is recommended for production environments to ensure reliability and performance.

For more details on Stellar RPC server integration, see the Stellar RPC Server Integration section.

6

Deploy the Application

ApiCharge is distributed as a platform-specific, self-contained native binary through our Early Access Program. Native binaries are available for Windows, Linux, and macOS platforms.

Extract your platform-specific ApiCharge native binary to the application directory:

cd /opt/apicharge/app

# For Linux x64 (example)
tar -xzf apicharge-linux-x64.tar.gz
chmod +x ApiChargePrototype

# For Windows x64 (example)
# Extract apicharge-win-x64.zip to C:\apicharge\app

# For macOS x64/arm64 (example)
tar -xzf apicharge-osx-x64.tar.gz  # or apicharge-osx-arm64.tar.gz
chmod +x ApiChargePrototype

These native binaries are compiled with AOT (Ahead-of-Time) technology, which results in improved startup performance and reduced memory footprint. Since they are self-contained, they don't require any .NET runtime to be installed on the target system.

7

Running the Application

The ApiCharge native binary can be run directly on any supported platform. You'll need to set the required environment variables and specify the listening URLs.

Windows
set APICHARGE_SIGNING_KEY=SDH3X...YOUR_STELLAR_SECRET_KEY
set APICHARGE_NETWORK_PASSPHRASE=Test SDF Network ; September 2015
set ASPNETCORE_ENVIRONMENT=Production

ApiChargePrototype.exe --urls="http://0.0.0.0:5000;https://0.0.0.0:5001"
Linux/macOS
export APICHARGE_SIGNING_KEY=SDH3X...YOUR_STELLAR_SECRET_KEY
export APICHARGE_NETWORK_PASSPHRASE="Test SDF Network ; September 2015"
export ASPNETCORE_ENVIRONMENT=Production

./ApiChargePrototype --urls="http://0.0.0.0:5000;https://0.0.0.0:5001"

For a complete list of environment variables, see the Environment Variables documentation.

For production deployments, you may want to create a startup script or service definition appropriate for your operating system.

8

Create Systemd Service

For production deployments, create a systemd service file at /etc/systemd/system/apicharge.service:

[Unit]
Description=ApiCharge API Monetization Service
After=network.target redis.service

[Service]
Type=simple
User=apicharge
Group=apicharge
WorkingDirectory=/opt/apicharge/app
ExecStart=/opt/apicharge/scripts/start.sh
Restart=always
RestartSec=10
SyslogIdentifier=apicharge
EnvironmentFile=/opt/apicharge/scripts/env.sh

# Security enhancements
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
ProtectHome=true

[Install]
WantedBy=multi-user.target

Create a dedicated user for the service:

sudo useradd -r -s /bin/false apicharge
sudo chown -R apicharge:apicharge /opt/apicharge

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable apicharge
sudo systemctl start apicharge
9

Configure Logging

ApiCharge logs to both the console and file by default. To configure log rotation, install and configure logrotate:

sudo apt-get install logrotate
sudo nano /etc/logrotate.d/apicharge

Add the following configuration:

/opt/apicharge/logs/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 apicharge apicharge
    sharedscripts
    postrotate
        systemctl reload apicharge
    endscript
}
10

Verify Installation

Check that the service is running correctly:

sudo systemctl status apicharge
curl http://localhost:5000/apicharge/health

If everything is configured correctly, the health endpoint should return a 200 OK status.

Configuration Examples

Basic Configuration

Here's a minimal configuration for testing purposes:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "GlobalSettings": {
    "UseNetwork": "Testnet",
    "SigningKeyEnvironmentVariable": "APICHARGE_SIGNING_KEY",
    "StellarNetworkPassphraseEnvironmentVariable": "APICHARGE_NETWORK_PASSPHRASE"
  },
  "ApiChargeQuotes": {
    "Quotes": [
      {
        "RouteId": "test-route",
        "Duration": 3600,
        "MicroUnitPrice": 100000,
        "RateLimiters": [
          {
            "$type": "CallCount",
            "Count": 100
          }
        ]
      }
    ]
  },
  "Routes": {
    "Clusters": [
      {
        "ClusterId": "testCluster",
        "Destinations": [
          {
            "Address": "http://localhost:8080"
          }
        ]
      }
    ],
    "Routes": [
      {
        "RouteId": "test-route",
        "ClusterId": "testCluster",
        "Match": {
          "Path": "/api/{**remainder}"
        }
      }
    ]
  }
}

Production Configuration

For production environments, consider this more comprehensive configuration:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    },
    "File": {
      "Path": "/opt/apicharge/logs/apicharge.log",
      "FileSizeLimitBytes": 10485760,
      "MaxRollingFiles": 10
    }
  },
  "GlobalSettings": {
    "UseNetwork": "Mainnet",
    "ToleratedClockSkew": "00:01:00",
    "QuoteValidityDuration": "01:00:00",
    "SigningKeyEnvironmentVariable": "APICHARGE_SIGNING_KEY",
    "StellarEndpointRPC": "https://soroban.stellar.org",
    "StellarNetworkPassphraseEnvironmentVariable": "APICHARGE_NETWORK_PASSPHRASE",
    "AllowSelfSignedServerCertificates": false
  },
  "ApiChargeQuotes": {
    "Quotes": [
      {
        "RouteId": "basic-api",
        "Duration": 3600,
        "MicroUnitPrice": 100000,
        "RateLimiters": [
          {
            "$type": "CallCount",
            "Count": 100
          },
          {
            "$type": "DataLimitDownload",
            "Bytes": 10485760
          }
        ]
      },
      {
        "RouteId": "standard-api",
        "Duration": 3600,
        "MicroUnitPrice": 250000,
        "RateLimiters": [
          {
            "$type": "CallCount",
            "Count": 500
          },
          {
            "$type": "DataLimitDownload",
            "Bytes": 52428800
          }
        ]
      },
      {
        "RouteId": "premium-api",
        "Duration": 3600,
        "MicroUnitPrice": 500000,
        "RateLimiters": [
          {
            "$type": "CallCount",
            "Count": 1000
          },
          {
            "$type": "DataLimitDownload",
            "Bytes": 104857600
          }
        ]
      }
    ]
  },
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "Https": {
        "Url": "https://0.0.0.0:5001",
        "Certificate": {
          "Path": "/opt/apicharge/config/certificate.pfx",
          "Password": "CERTIFICATE_PASSWORD_HERE"
        }
      }
    },
    "AddServerHeader": false
  },
  "Redis": {
    "ConnectionString": "redis.example.com:6379,password=YOUR_REDIS_PASSWORD,ssl=true,abortConnect=false",
    "InstanceName": "ApiCharge-Prod-"
  },
  "RateLimiterPersistence": {
    "UseRedis": true,
    "PersistenceIntervalSeconds": 10,
    "RedisExpiryMultiplier": 2
  },
  "Routes": {
    "Clusters": [
      {
        "ClusterId": "apiCluster",
        "Destinations": [
          {
            "Address": "https://api-backend-1.example.com",
            "Health": {
              "Active": {
                "Enabled": true,
                "Interval": "00:00:10",
                "Timeout": "00:00:10",
                "Path": "/health"
              }
            }
          },
          {
            "Address": "https://api-backend-2.example.com",
            "Health": {
              "Active": {
                "Enabled": true,
                "Interval": "00:00:10",
                "Timeout": "00:00:10",
                "Path": "/health"
              }
            }
          }
        ],
        "HttpClient": {
          "MaxConnectionsPerServer": 100,
          "DangerousAcceptAnyServerCertificate": false,
          "RequestHeaderEncoding": "utf-8",
          "ResponseHeaderEncoding": "utf-8"
        },
        "LoadBalancingPolicy": {
          "Type": "RoundRobin"
        },
        "HealthCheck": {
          "Active": {
            "Enabled": true,
            "Interval": "00:00:10",
            "Timeout": "00:00:05",
            "Path": "/health"
          },
          "Passive": {
            "Enabled": true,
            "ReactivationPeriod": "00:00:10"
          }
        }
      }
    ],
    "Routes": [
      {
        "RouteId": "basic-api",
        "ClusterId": "apiCluster",
        "Match": {
          "Path": "/api/basic/{**remainder}",
          "Methods": [ "GET" ]
        },
        "Transforms": [
          { "PathPattern": "/api/v1/{**remainder}" }
        ]
      },
      {
        "RouteId": "standard-api",
        "ClusterId": "apiCluster",
        "Match": {
          "Path": "/api/standard/{**remainder}",
          "Methods": [ "GET", "POST" ]
        },
        "Transforms": [
          { "PathPattern": "/api/v1/{**remainder}" },
          { "RequestHeadersCopy": "true" },
          { "RequestHeaderOriginalHost": "true" }
        ]
      },
      {
        "RouteId": "premium-api",
        "ClusterId": "apiCluster",
        "Match": {
          "Path": "/api/premium/{**remainder}"
        },
        "Transforms": [
          { "PathPrefix": "/api/v2" },
          { "RequestHeadersCopy": "true" },
          { "RequestHeaderOriginalHost": "true" },
          { "X-Forwarded": "proto,host,for,prefix" }
        ]
      }
    ]
  }
}

Stellar RPC Server Management

For standalone deployments with the native binary, you must use an external Stellar RPC server:

External RPC Server Configuration

Configure your ApiCharge to connect to an external Stellar RPC server by setting the StellarEndpointRPC in your appsettings.json:

{
  "ApiChargeProxy": {
    "Global": {
      "UseNetwork": "Testnet",
      "StellarEndpointRPC": "http://localhost:8000",
      // Other settings...
    }
  }
}

You can use:

Benefits of External RPC Server

Using an external Stellar RPC server offers several advantages:

For more details, see the Stellar RPC Server Integration documentation.

Logging Configuration

ApiCharge uses the standard .NET logging framework to capture information about the service's operations. Proper logging configuration is essential for monitoring, troubleshooting, and auditing your ApiCharge service.

Basic logging configuration in appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  }
}

For detailed information about logging configuration options, see the Logging Configuration documentation.

Maintenance and Operations

Backup Strategy

Regularly back up these critical components:

Monitoring

Monitor ApiCharge using standard HTTP monitoring tools:

Updating ApiCharge

To update ApiCharge to a new version:

# Stop the service
sudo systemctl stop apicharge

# Backup current version
cp -r /opt/apicharge/app /opt/apicharge/app.bak

# Download and extract new version
cd /opt/apicharge
wget https://github.com/apicharge/apicharge/releases/download/v1.1.0/apicharge-standalone.zip
unzip -o apicharge-standalone.zip -d app
rm apicharge-standalone.zip

# Update permissions
chown -R apicharge:apicharge /opt/apicharge/app

# Start the service
sudo systemctl start apicharge

# Verify the update
curl http://localhost:5000/apicharge/health

Troubleshooting

Common issues and solutions for standalone deployments:

Service Won't Start

Authentication Errors

Blockchain Connection Issues

For more troubleshooting tips, see the Troubleshooting documentation.

Next Steps

After setting up your standalone deployment, consider exploring: