Termcloud

A Mullvad-style file storage service with Bitcoin payments and usage-based billing.

Features

  • Account-based System: Anonymous account creation with 16-digit account numbers
  • Bitcoin Payments: Pay with Bitcoin to activate and fund your account
  • Usage-based Billing: Charged monthly for peak storage usage (pay for what you use)
  • Bucket Policies: AWS S3-compatible JSON policies for access control
  • RESTful API: Complete REST API for all operations

Authentication System

Similar to Mullvad VPN:

  1. Create Account: Generate anonymous 16-digit account number + access token
  2. Add Funds: Pay ~$5 worth of Bitcoin to activate account
  3. Usage Billing: Charged monthly based on peak storage usage ($0.50/GB default)
  4. No Personal Info: No emails, usernames, or personal information required

Setup

  1. Set up PostgreSQL database and run the schema:
psql -d termcloud -f internal/db/schema.sql
  1. Configure environment variables (copy .env.example to .env and customize):
cp .env.example .env
# Edit .env with your settings

Configuration Options

Variable Default Description
PRICE_PER_GB_USD 0.50 Monthly charge per GB of peak storage
DATABASE_URL - PostgreSQL connection string
PORT 8080 Server port
STORAGE_DIR storage Directory for file storage
  1. Build and run:
make build
make run

Usage

1. Create Account

curl -X POST http://localhost:8080/api/v1/accounts

Response:

{
  "accountNumber": "1234567890123456",
  "accessToken": "abc123...",
  "balanceUsd": 0.00,
  "isActive": false,
  "message": "Account created. Add funds to activate."
}

2. Add Funds (Bitcoin Payment)

curl -X POST http://localhost:8080/api/v1/account/payments \
  -H "X-Access-Token: your-access-token" \
  -H "Content-Type: application/json" \
  -d '{"amount": 5.00}'

3. Use Storage (requires active account)

All storage endpoints require X-Access-Token header:

API Endpoints

All API endpoints require X-API-Key header.

Buckets:

  • GET /api/v1/buckets - List user buckets
  • POST /api/v1/buckets - Create bucket {"name": "my-bucket"}
  • DELETE /api/v1/buckets/:bucket - Delete bucket

Objects:

  • GET /api/v1/buckets/:bucket/objects - List objects in bucket
  • PUT /api/v1/buckets/:bucket/objects/* - Upload file (multipart form with "file" field)
  • GET /api/v1/buckets/:bucket/objects/* - Download file
  • DELETE /api/v1/buckets/:bucket/objects/* - Delete file

User Info:

  • GET /api/v1/user - Get user info and usage stats

Bucket Policies:

  • PUT /api/v1/buckets/:bucket/policy - Set bucket policy {"policy": "json-policy-string"}
  • GET /api/v1/buckets/:bucket/policy - Get bucket policy
  • DELETE /api/v1/buckets/:bucket/policy - Delete bucket policy

Bucket Policies

Bucket policies use JSON format similar to AWS S3 IAM policies to control access to buckets and objects.

Policy Structure

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "StatementId",
      "Effect": "Allow|Deny",
      "Principal": {
        "User": ["username1", "username2"]
      },
      "Action": [
        "termcloud:GetObject",
        "termcloud:PutObject",
        "termcloud:DeleteObject",
        "termcloud:ListObjects"
      ],
      "Resource": [
        "arn:termcloud:s3:::bucket-name/*"
      ]
    }
  ]
}

Supported Actions

  • termcloud:GetObject - Download files
  • termcloud:PutObject - Upload files
  • termcloud:DeleteObject - Delete files
  • termcloud:ListObjects - List files in bucket
  • termcloud:GetBucket - Get bucket info
  • termcloud:DeleteBucket - Delete bucket
  • * - All actions

Policy Examples

Read-only access:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"User": ["john"]},
      "Action": ["termcloud:GetObject", "termcloud:ListObjects"],
      "Resource": ["arn:termcloud:s3:::my-bucket/*"]
    }
  ]
}

Deny delete operations:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": {"User": ["*"]},
      "Action": ["termcloud:DeleteObject"],
      "Resource": ["arn:termcloud:s3:::my-bucket/*"]
    }
  ]
}

Example Usage

# Create bucket
curl -X POST http://localhost:8080/api/v1/buckets \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-files"}'

# Upload file
curl -X PUT http://localhost:8080/api/v1/buckets/my-files/objects/test.txt \
  -H "X-API-Key: your-api-key" \
  -F "file=@test.txt"

# Download file
curl http://localhost:8080/api/v1/buckets/my-files/objects/test.txt \
  -H "X-API-Key: your-api-key" \
  -o downloaded.txt
Description
No description provided
Readme 139 KiB
Languages
Go 94.7%
PLpgSQL 4.5%
Makefile 0.8%