Autarch/services/setec-manager/docs/hosting-providers.md
2026-03-12 20:51:38 -07:00

17 KiB

Hosting Provider Integration System

Overview

Setec Manager includes a pluggable hosting provider architecture that lets you manage DNS records, domains, VPS instances, SSH keys, and billing subscriptions through a unified interface. The system is built around a Go Provider interface defined in internal/hosting/provider.go. Each hosting provider (e.g., Hostinger) implements this interface and auto-registers itself at import time via an init() function.

Architecture

internal/hosting/
  provider.go    -- Provider interface, model types, global registry
  store.go       -- ProviderConfig type, ProviderConfigStore (disk persistence)
  config.go      -- Legacy config store (being superseded by store.go)
  hostinger/
    client.go    -- Hostinger HTTP client with retry/rate-limit handling
    dns.go       -- Hostinger DNS implementation

The registry is a process-global map[string]Provider guarded by a sync.RWMutex. Providers call hosting.Register(&Provider{}) inside their package init() function. The main binary imports the provider package (e.g., _ "setec-manager/internal/hosting/hostinger") to trigger registration.

Provider credentials are stored as individual JSON files in a protected directory (0700 directory, 0600 files) managed by ProviderConfigStore. Each file is named <provider>.json and contains the ProviderConfig struct:

{
  "provider": "hostinger",
  "api_key": "Bearer ...",
  "api_secret": "",
  "extra": {},
  "connected": true
}

Supported Providers

Hostinger (Built-in)

Capability Supported Notes
DNS Management Yes Full CRUD, validation before writes, zone reset
Domain Management Yes List, lookup, availability check, purchase, nameservers, lock, privacy
VPS Management Yes List, create, get details, data center listing
SSH Key Management Yes Add, list, delete
Billing Yes Subscriptions and catalog

The Hostinger provider communicates with https://developers.hostinger.com using a Bearer token. It includes automatic retry with back-off on HTTP 429 (rate limit) responses, up to 3 retries per request.


Configuration

Via the UI

  1. Navigate to the Hosting Providers section in the Setec Manager dashboard.
  2. Select "Hostinger" from the provider list.
  3. Enter your API token (obtained from hPanel -- see Hostinger Setup Guide).
  4. Click "Test Connection" to verify the token is valid.
  5. Click "Save" to persist the configuration.

Via Config Files

Provider configurations are stored as JSON files in the config directory (typically /opt/setec-manager/data/hosting/).

Create or edit the file directly:

mkdir -p /opt/setec-manager/data/hosting
cat > /opt/setec-manager/data/hosting/hostinger.json << 'EOF'
{
  "provider": "hostinger",
  "api_key": "YOUR_BEARER_TOKEN_HERE",
  "api_secret": "",
  "extra": {},
  "connected": true
}
EOF
chmod 600 /opt/setec-manager/data/hosting/hostinger.json

Via API

curl -X POST https://your-server:9090/api/hosting/providers/hostinger/configure \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_HOSTINGER_API_TOKEN"
  }'

API Reference

All hosting endpoints require authentication via JWT (cookie or Authorization: Bearer header). The base URL is https://your-server:9090.

Provider Management

List Providers

GET /api/hosting/providers

Returns all registered hosting providers and their connection status.

curl -s https://your-server:9090/api/hosting/providers \
  -H "Authorization: Bearer $TOKEN"

Response:

[
  {
    "name": "hostinger",
    "display_name": "Hostinger",
    "connected": true
  }
]

Configure Provider

POST /api/hosting/providers/{provider}/configure

Sets the API credentials for a provider.

curl -X POST https://your-server:9090/api/hosting/providers/hostinger/configure \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_API_TOKEN"
  }'

Response:

{
  "status": "configured"
}

Test Connection

POST /api/hosting/providers/{provider}/test

Verifies that the saved credentials are valid by making a test API call.

curl -X POST https://your-server:9090/api/hosting/providers/hostinger/test \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "ok",
  "message": "Connection successful"
}

Remove Provider Configuration

DELETE /api/hosting/providers/{provider}

Deletes saved credentials for a provider.

curl -X DELETE https://your-server:9090/api/hosting/providers/hostinger \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "deleted"
}

DNS Management

List DNS Records

GET /api/hosting/providers/{provider}/dns/{domain}

Returns all DNS records for the specified domain.

curl -s https://your-server:9090/api/hosting/providers/hostinger/dns/example.com \
  -H "Authorization: Bearer $TOKEN"

Response:

[
  {
    "id": "@/A/0",
    "type": "A",
    "name": "@",
    "content": "93.184.216.34",
    "ttl": 14400,
    "priority": 0
  },
  {
    "id": "www/CNAME/0",
    "type": "CNAME",
    "name": "www",
    "content": "example.com",
    "ttl": 14400,
    "priority": 0
  },
  {
    "id": "@/MX/10",
    "type": "MX",
    "name": "@",
    "content": "mail.example.com",
    "ttl": 14400,
    "priority": 10
  }
]

Create DNS Record

POST /api/hosting/providers/{provider}/dns/{domain}

Adds a new DNS record without overwriting existing records.

curl -X POST https://your-server:9090/api/hosting/providers/hostinger/dns/example.com \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "A",
    "name": "api",
    "content": "93.184.216.35",
    "ttl": 3600
  }'

Response:

{
  "status": "created"
}

Update DNS Records (Batch)

PUT /api/hosting/providers/{provider}/dns/{domain}

Updates DNS records for a domain. If overwrite is true, all existing records are replaced; otherwise the records are merged.

The Hostinger provider validates records against the API before applying changes.

curl -X PUT https://your-server:9090/api/hosting/providers/hostinger/dns/example.com \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "records": [
      {
        "type": "A",
        "name": "@",
        "content": "93.184.216.34",
        "ttl": 14400
      },
      {
        "type": "CNAME",
        "name": "www",
        "content": "example.com",
        "ttl": 14400
      }
    ],
    "overwrite": false
  }'

Response:

{
  "status": "updated"
}

Delete DNS Record

DELETE /api/hosting/providers/{provider}/dns/{domain}?name={name}&type={type}

Removes DNS records matching the given name and type.

curl -X DELETE "https://your-server:9090/api/hosting/providers/hostinger/dns/example.com?name=api&type=A" \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "deleted"
}

Reset DNS Zone

POST /api/hosting/providers/{provider}/dns/{domain}/reset

Resets the domain's DNS zone to the provider's default records. This is destructive and removes all custom records.

curl -X POST https://your-server:9090/api/hosting/providers/hostinger/dns/example.com/reset \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "reset"
}

Supported DNS Record Types

Type Description Priority Field
A IPv4 address No
AAAA IPv6 address No
CNAME Canonical name / alias No
MX Mail exchange Yes
TXT Text record (SPF, DKIM, etc.) No
NS Name server No
SRV Service record Yes
CAA Certificate Authority Authorization No

Domain Management

List Domains

GET /api/hosting/providers/{provider}/domains
curl -s https://your-server:9090/api/hosting/providers/hostinger/domains \
  -H "Authorization: Bearer $TOKEN"

Response:

[
  {
    "name": "example.com",
    "registrar": "Hostinger",
    "status": "active",
    "expires_at": "2027-03-15T00:00:00Z",
    "auto_renew": true,
    "locked": true,
    "privacy_protection": true,
    "nameservers": ["ns1.dns-parking.com", "ns2.dns-parking.com"]
  }
]

Get Domain Details

GET /api/hosting/providers/{provider}/domains/{domain}
curl -s https://your-server:9090/api/hosting/providers/hostinger/domains/example.com \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "name": "example.com",
  "registrar": "Hostinger",
  "status": "active",
  "expires_at": "2027-03-15T00:00:00Z",
  "auto_renew": true,
  "locked": true,
  "privacy_protection": true,
  "nameservers": ["ns1.dns-parking.com", "ns2.dns-parking.com"]
}

Check Domain Availability

POST /api/hosting/providers/{provider}/domains/check
curl -X POST https://your-server:9090/api/hosting/providers/hostinger/domains/check \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "domains": ["cool-project.com", "cool-project.io", "cool-project.dev"]
  }'

Response:

[
  {
    "domain": "cool-project.com",
    "available": true,
    "price": 9.99,
    "currency": "USD"
  },
  {
    "domain": "cool-project.io",
    "available": false
  },
  {
    "domain": "cool-project.dev",
    "available": true,
    "price": 14.99,
    "currency": "USD"
  }
]

Purchase Domain

POST /api/hosting/providers/{provider}/domains/purchase
curl -X POST https://your-server:9090/api/hosting/providers/hostinger/domains/purchase \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "cool-project.com",
    "period": 1,
    "auto_renew": true,
    "privacy_protection": true,
    "payment_method_id": "pm_abc123"
  }'

Response:

{
  "name": "cool-project.com",
  "status": "active",
  "expires_at": "2027-03-11T00:00:00Z",
  "auto_renew": true,
  "locked": false,
  "privacy_protection": true,
  "nameservers": ["ns1.dns-parking.com", "ns2.dns-parking.com"]
}

Set Nameservers

PUT /api/hosting/providers/{provider}/domains/{domain}/nameservers
curl -X PUT https://your-server:9090/api/hosting/providers/hostinger/domains/example.com/nameservers \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "nameservers": ["ns1.cloudflare.com", "ns2.cloudflare.com"]
  }'

Response:

{
  "status": "updated"
}

Enable Domain Lock

POST /api/hosting/providers/{provider}/domains/{domain}/lock

Prevents unauthorized domain transfers.

curl -X POST https://your-server:9090/api/hosting/providers/hostinger/domains/example.com/lock \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "locked"
}

Disable Domain Lock

DELETE /api/hosting/providers/{provider}/domains/{domain}/lock
curl -X DELETE https://your-server:9090/api/hosting/providers/hostinger/domains/example.com/lock \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "unlocked"
}

Enable Privacy Protection

POST /api/hosting/providers/{provider}/domains/{domain}/privacy

Enables WHOIS privacy protection to hide registrant details.

curl -X POST https://your-server:9090/api/hosting/providers/hostinger/domains/example.com/privacy \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "enabled"
}

Disable Privacy Protection

DELETE /api/hosting/providers/{provider}/domains/{domain}/privacy
curl -X DELETE https://your-server:9090/api/hosting/providers/hostinger/domains/example.com/privacy \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "disabled"
}

VPS Management

List Virtual Machines

GET /api/hosting/providers/{provider}/vms
curl -s https://your-server:9090/api/hosting/providers/hostinger/vms \
  -H "Authorization: Bearer $TOKEN"

Response:

[
  {
    "id": "vm-abc123",
    "name": "production-1",
    "status": "running",
    "plan": "kvm-2",
    "region": "us-east-1",
    "ipv4": "93.184.216.34",
    "ipv6": "2606:2800:220:1:248:1893:25c8:1946",
    "os": "Ubuntu 22.04",
    "cpus": 2,
    "memory_mb": 4096,
    "disk_gb": 80,
    "bandwidth_gb": 4000,
    "created_at": "2025-01-15T10:30:00Z",
    "labels": {
      "env": "production"
    }
  }
]

Get VM Details

GET /api/hosting/providers/{provider}/vms/{id}
curl -s https://your-server:9090/api/hosting/providers/hostinger/vms/vm-abc123 \
  -H "Authorization: Bearer $TOKEN"

Response: Same shape as a single item from the list response.

Create VM

POST /api/hosting/providers/{provider}/vms
curl -X POST https://your-server:9090/api/hosting/providers/hostinger/vms \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "plan": "kvm-2",
    "data_center_id": "us-east-1",
    "template": "ubuntu-22.04",
    "password": "SecurePassword123!",
    "hostname": "web-server-2",
    "ssh_key_id": "key-abc123",
    "payment_method_id": "pm_abc123"
  }'

Response:

{
  "id": "vm-def456",
  "name": "web-server-2",
  "status": "creating",
  "plan": "kvm-2",
  "region": "us-east-1",
  "os": "Ubuntu 22.04",
  "cpus": 2,
  "memory_mb": 4096,
  "disk_gb": 80,
  "bandwidth_gb": 4000,
  "created_at": "2026-03-11T14:00:00Z"
}

List Data Centers

GET /api/hosting/providers/{provider}/datacenters

Returns available regions/data centers for VM creation.

curl -s https://your-server:9090/api/hosting/providers/hostinger/datacenters \
  -H "Authorization: Bearer $TOKEN"

Response:

[
  {
    "id": "us-east-1",
    "name": "US East",
    "location": "New York",
    "country": "US"
  },
  {
    "id": "eu-west-1",
    "name": "EU West",
    "location": "Amsterdam",
    "country": "NL"
  }
]

SSH Key Management

List SSH Keys

GET /api/hosting/providers/{provider}/ssh-keys
curl -s https://your-server:9090/api/hosting/providers/hostinger/ssh-keys \
  -H "Authorization: Bearer $TOKEN"

Response:

[
  {
    "id": "key-abc123",
    "name": "deploy-key",
    "fingerprint": "SHA256:abcd1234...",
    "public_key": "ssh-ed25519 AAAAC3Nz..."
  }
]

Add SSH Key

POST /api/hosting/providers/{provider}/ssh-keys
curl -X POST https://your-server:9090/api/hosting/providers/hostinger/ssh-keys \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "new-deploy-key",
    "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@host"
  }'

Response:

{
  "id": "key-def456",
  "name": "new-deploy-key",
  "fingerprint": "SHA256:efgh5678...",
  "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..."
}

Delete SSH Key

DELETE /api/hosting/providers/{provider}/ssh-keys/{id}
curl -X DELETE https://your-server:9090/api/hosting/providers/hostinger/ssh-keys/key-def456 \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "status": "deleted"
}

Billing

List Subscriptions

GET /api/hosting/providers/{provider}/subscriptions
curl -s https://your-server:9090/api/hosting/providers/hostinger/subscriptions \
  -H "Authorization: Bearer $TOKEN"

Response:

[
  {
    "id": "sub-abc123",
    "name": "Premium Web Hosting",
    "status": "active",
    "plan": "premium-hosting-48m",
    "price": 2.99,
    "currency": "USD",
    "renews_at": "2027-03-15T00:00:00Z",
    "created_at": "2023-03-15T00:00:00Z"
  }
]

Get Product Catalog

GET /api/hosting/providers/{provider}/catalog
curl -s https://your-server:9090/api/hosting/providers/hostinger/catalog \
  -H "Authorization: Bearer $TOKEN"

Response:

[
  {
    "id": "kvm-2",
    "name": "KVM 2",
    "category": "vps",
    "price_cents": 1199,
    "currency": "USD",
    "period": "monthly",
    "description": "2 vCPU, 4 GB RAM, 80 GB SSD"
  },
  {
    "id": "premium-hosting-12m",
    "name": "Premium Web Hosting",
    "category": "hosting",
    "price_cents": 299,
    "currency": "USD",
    "period": "monthly",
    "description": "100 websites, 100 GB SSD, free SSL"
  }
]

Error Responses

All endpoints return errors in a consistent format:

{
  "error": "description of what went wrong"
}
HTTP Status Meaning
400 Bad request (invalid parameters)
401 Authentication required or token invalid
404 Provider or resource not found
409 Conflict (e.g., duplicate resource)
429 Rate limited by the upstream provider
500 Internal server error
501 Provider does not support this operation (ErrNotSupported)

When a provider does not implement a particular capability, the endpoint returns HTTP 501 with an ErrNotSupported error message. This allows partial implementations where a provider only supports DNS management, for example.