diff --git a/docs/api/HETZNER_API_README.md b/docs/api/HETZNER_API_README.md deleted file mode 100644 index 8501aeb75..000000000 --- a/docs/api/HETZNER_API_README.md +++ /dev/null @@ -1,256 +0,0 @@ -# Hetzner Server Provisioning via API - -This implementation adds full API support for Hetzner server provisioning in Coolify, matching the functionality available in the UI. - -## What's New - -### API Endpoints - -#### Cloud Provider Tokens -- `GET /api/v1/cloud-tokens` - List all cloud provider tokens -- `POST /api/v1/cloud-tokens` - Create a new cloud provider token (with validation) -- `GET /api/v1/cloud-tokens/{uuid}` - Get a specific token -- `PATCH /api/v1/cloud-tokens/{uuid}` - Update token name -- `DELETE /api/v1/cloud-tokens/{uuid}` - Delete token (prevents deletion if used by servers) -- `POST /api/v1/cloud-tokens/{uuid}/validate` - Validate token against provider API - -#### Hetzner Resources -- `GET /api/v1/hetzner/locations` - List Hetzner datacenter locations -- `GET /api/v1/hetzner/server-types` - List server types (filters deprecated) -- `GET /api/v1/hetzner/images` - List OS images (filters deprecated & non-system) -- `GET /api/v1/hetzner/ssh-keys` - List SSH keys from Hetzner account - -#### Hetzner Server Provisioning -- `POST /api/v1/servers/hetzner` - Create a new Hetzner server - -## Files Added/Modified - -### Controllers -- `app/Http/Controllers/Api/CloudProviderTokensController.php` - Cloud token CRUD operations -- `app/Http/Controllers/Api/HetznerController.php` - Hetzner provisioning operations - -### Routes -- `routes/api.php` - Added new API routes - -### Tests -- `tests/Feature/CloudProviderTokenApiTest.php` - Comprehensive tests for cloud tokens -- `tests/Feature/HetznerApiTest.php` - Comprehensive tests for Hetzner provisioning - -### Documentation -- `docs/api/hetzner-provisioning-examples.md` - Complete curl examples -- `docs/api/hetzner-yaak-collection.json` - Importable Yaak/Postman collection -- `docs/api/HETZNER_API_README.md` - This file - -## Features - -### Authentication & Authorization -- All endpoints require Sanctum authentication -- Cloud token operations restricted to team members -- Follows existing API patterns for consistency - -### Token Validation -- Tokens are validated against provider APIs before storage -- Supports both Hetzner and DigitalOcean -- Encrypted storage of API tokens - -### Smart SSH Key Management -- Automatic MD5 fingerprint matching to avoid duplicate uploads -- Supports Coolify private key + additional Hetzner keys -- Automatic deduplication - -### Network Configuration -- IPv4/IPv6 toggle support -- Prefers IPv4 when both enabled -- Validates at least one network type is enabled - -### Cloud-init Support -- Optional cloud-init script for server initialization -- YAML validation using existing ValidCloudInitYaml rule - -### Server Creation Flow -1. Validates cloud provider token and private key -2. Uploads SSH key to Hetzner if not already present -3. Creates server on Hetzner with all specified options -4. Registers server in Coolify database -5. Sets up default proxy configuration (Traefik) -6. Optional instant validation - -## Testing - -### Running Tests - -**Feature Tests (require database):** -```bash -# Run inside Docker -docker exec coolify php artisan test --filter=CloudProviderTokenApiTest -docker exec coolify php artisan test --filter=HetznerApiTest -``` - -### Test Coverage - -**CloudProviderTokenApiTest:** -- ✅ List all tokens (with team isolation) -- ✅ Get specific token -- ✅ Create Hetzner token (with API validation) -- ✅ Create DigitalOcean token (with API validation) -- ✅ Update token name -- ✅ Delete token (prevents if used by servers) -- ✅ Validate token -- ✅ Validation errors for all required fields -- ✅ Extra field rejection -- ✅ Authentication checks - -**HetznerApiTest:** -- ✅ Get locations -- ✅ Get server types (filters deprecated) -- ✅ Get images (filters deprecated & non-system) -- ✅ Get SSH keys -- ✅ Create server (minimal & full options) -- ✅ IPv4/IPv6 preference logic -- ✅ Auto-generate server name -- ✅ Validation for all required fields -- ✅ Token & key existence validation -- ✅ Extra field rejection -- ✅ Authentication checks - -## Usage Examples - -### Quick Start - -```bash -# 1. Create a cloud provider token -curl -X POST "http://localhost/api/v1/cloud-tokens" \ - -H "Authorization: Bearer root" \ - -H "Content-Type: application/json" \ - -d '{ - "provider": "hetzner", - "token": "YOUR_HETZNER_API_TOKEN", - "name": "My Hetzner Token" - }' - -# Save the returned UUID as CLOUD_TOKEN_UUID - -# 2. Get available locations -curl -X GET "http://localhost/api/v1/hetzner/locations?cloud_provider_token_id=CLOUD_TOKEN_UUID" \ - -H "Authorization: Bearer root" - -# 3. Get your private key UUID -curl -X GET "http://localhost/api/v1/security/keys" \ - -H "Authorization: Bearer root" - -# Save the returned UUID as PRIVATE_KEY_UUID - -# 4. Create a server -curl -X POST "http://localhost/api/v1/servers/hetzner" \ - -H "Authorization: Bearer root" \ - -H "Content-Type: application/json" \ - -d '{ - "cloud_provider_token_id": "CLOUD_TOKEN_UUID", - "location": "nbg1", - "server_type": "cx11", - "image": 67794396, - "private_key_uuid": "PRIVATE_KEY_UUID" - }' -``` - -For complete examples, see: -- **[hetzner-provisioning-examples.md](./hetzner-provisioning-examples.md)** - Detailed curl examples -- **[hetzner-yaak-collection.json](./hetzner-yaak-collection.json)** - Import into Yaak - -## API Design Decisions - -### Consistency with Existing API -- Follows patterns from `ServersController` -- Uses same validation approach (inline with `customApiValidator`) -- Uses same response formatting (`serializeApiResponse`) -- Uses same error handling patterns - -### Reuses Existing Code -- `HetznerService` - All Hetzner API calls -- `ValidHostname` rule - Server name validation -- `ValidCloudInitYaml` rule - Cloud-init validation -- `PrivateKey::generateMd5Fingerprint()` - SSH key fingerprinting - -### Team Isolation -- All endpoints filter by team ID from API token -- Cannot access tokens/servers from other teams -- Follows existing security patterns - -### Error Handling -- Provider API errors wrapped in generic messages (doesn't leak Hetzner errors) -- Validation errors with clear field-specific messages -- 404 for resources not found -- 422 for validation failures -- 400 for business logic errors (e.g., token validation failure) - -## Next Steps - -To use this in production: - -1. **Run Pint** (code formatting): - ```bash - cd /Users/heyandras/devel/coolify - ./vendor/bin/pint --dirty - ``` - -2. **Run Tests** (inside Docker): - ```bash - docker exec coolify php artisan test --filter=CloudProviderTokenApiTest - docker exec coolify php artisan test --filter=HetznerApiTest - ``` - -3. **Commit Changes**: - ```bash - git add . - git commit -m "feat: add Hetzner server provisioning API endpoints - - - Add CloudProviderTokensController for token CRUD operations - - Add HetznerController for server provisioning - - Add comprehensive feature tests - - Add curl examples and Yaak collection - - Reuse existing HetznerService and validation rules - - Support IPv4/IPv6 configuration - - Support cloud-init scripts - - Smart SSH key management with deduplication" - ``` - -4. **Create Pull Request**: - ```bash - git push origin hetzner-api-provisioning - gh pr create --title "Add Hetzner Server Provisioning API" \ - --body "$(cat docs/api/HETZNER_API_README.md)" - ``` - -## Security Considerations - -- ✅ Tokens encrypted at rest (using Laravel's encrypted cast) -- ✅ Team-based isolation enforced -- ✅ API tokens validated before storage -- ✅ Rate limiting handled by HetznerService -- ✅ No sensitive data in responses (token field hidden) -- ✅ Authorization checks match UI (admin-only for token operations) -- ✅ Extra field validation prevents injection attacks - -## Compatibility - -- **Laravel**: 12.x -- **PHP**: 8.4 -- **Existing UI**: Fully compatible, shares same service layer -- **Database**: Uses existing schema (cloud_provider_tokens, servers tables) - -## Future Enhancements - -Potential additions: -- [ ] DigitalOcean server provisioning endpoints -- [ ] Server power management (start/stop/reboot) -- [ ] Server resize/upgrade endpoints -- [ ] Batch server creation -- [ ] Server templates/presets -- [ ] Webhooks for server events - -## Support - -For issues or questions: -- Check [hetzner-provisioning-examples.md](./hetzner-provisioning-examples.md) for usage examples -- Review test files for expected behavior -- See existing `HetznerService` for Hetzner API details diff --git a/docs/api/hetzner-provisioning-examples.md b/docs/api/hetzner-provisioning-examples.md deleted file mode 100644 index 7cf69100a..000000000 --- a/docs/api/hetzner-provisioning-examples.md +++ /dev/null @@ -1,464 +0,0 @@ -# Hetzner Server Provisioning API Examples - -This document contains ready-to-use curl examples for the Hetzner server provisioning API endpoints. These examples use the `root` API token for development and can be easily imported into Yaak or any other API client. - -## Prerequisites - -```bash -# Set these environment variables -export COOLIFY_URL="http://localhost" -export API_TOKEN="root" # Your Coolify API token -``` - -## Cloud Provider Tokens - -### 1. Create a Hetzner Cloud Provider Token - -```bash -curl -X POST "${COOLIFY_URL}/api/v1/cloud-tokens" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" \ - -d '{ - "provider": "hetzner", - "token": "YOUR_HETZNER_API_TOKEN_HERE", - "name": "My Hetzner Token" - }' -``` - -**Response:** -```json -{ - "uuid": "abc123def456" -} -``` - -### 2. List All Cloud Provider Tokens - -```bash -curl -X GET "${COOLIFY_URL}/api/v1/cloud-tokens" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -**Response:** -```json -[ - { - "uuid": "abc123def456", - "name": "My Hetzner Token", - "provider": "hetzner", - "team_id": 0, - "servers_count": 0, - "created_at": "2025-11-19T12:00:00.000000Z", - "updated_at": "2025-11-19T12:00:00.000000Z" - } -] -``` - -### 3. Get a Specific Cloud Provider Token - -```bash -curl -X GET "${COOLIFY_URL}/api/v1/cloud-tokens/abc123def456" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -### 4. Update Cloud Provider Token Name - -```bash -curl -X PATCH "${COOLIFY_URL}/api/v1/cloud-tokens/abc123def456" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "Production Hetzner Token" - }' -``` - -### 5. Validate a Cloud Provider Token - -```bash -curl -X POST "${COOLIFY_URL}/api/v1/cloud-tokens/abc123def456/validate" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -**Response:** -```json -{ - "valid": true, - "message": "Token is valid." -} -``` - -### 6. Delete a Cloud Provider Token - -```bash -curl -X DELETE "${COOLIFY_URL}/api/v1/cloud-tokens/abc123def456" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -**Response:** -```json -{ - "message": "Cloud provider token deleted." -} -``` - -## Hetzner Resource Discovery - -### 7. Get Available Hetzner Locations - -```bash -curl -X GET "${COOLIFY_URL}/api/v1/hetzner/locations?cloud_provider_token_id=abc123def456" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -**Response:** -```json -[ - { - "id": 1, - "name": "fsn1", - "description": "Falkenstein DC Park 1", - "country": "DE", - "city": "Falkenstein", - "latitude": 50.47612, - "longitude": 12.370071 - }, - { - "id": 2, - "name": "nbg1", - "description": "Nuremberg DC Park 1", - "country": "DE", - "city": "Nuremberg", - "latitude": 49.452102, - "longitude": 11.076665 - }, - { - "id": 3, - "name": "hel1", - "description": "Helsinki DC Park 1", - "country": "FI", - "city": "Helsinki", - "latitude": 60.169857, - "longitude": 24.938379 - } -] -``` - -### 8. Get Available Hetzner Server Types - -```bash -curl -X GET "${COOLIFY_URL}/api/v1/hetzner/server-types?cloud_provider_token_id=abc123def456" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -**Response (truncated):** -```json -[ - { - "id": 1, - "name": "cx11", - "description": "CX11", - "cores": 1, - "memory": 2.0, - "disk": 20, - "prices": [ - { - "location": "fsn1", - "price_hourly": { - "net": "0.0052000000", - "gross": "0.0061880000" - }, - "price_monthly": { - "net": "3.2900000000", - "gross": "3.9151000000" - } - } - ], - "storage_type": "local", - "cpu_type": "shared", - "architecture": "x86", - "deprecated": false - } -] -``` - -### 9. Get Available Hetzner Images (Operating Systems) - -```bash -curl -X GET "${COOLIFY_URL}/api/v1/hetzner/images?cloud_provider_token_id=abc123def456" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -**Response (truncated):** -```json -[ - { - "id": 15512617, - "name": "ubuntu-20.04", - "description": "Ubuntu 20.04", - "type": "system", - "os_flavor": "ubuntu", - "os_version": "20.04", - "architecture": "x86", - "deprecated": false - }, - { - "id": 67794396, - "name": "ubuntu-22.04", - "description": "Ubuntu 22.04", - "type": "system", - "os_flavor": "ubuntu", - "os_version": "22.04", - "architecture": "x86", - "deprecated": false - } -] -``` - -### 10. Get Hetzner SSH Keys - -```bash -curl -X GET "${COOLIFY_URL}/api/v1/hetzner/ssh-keys?cloud_provider_token_id=abc123def456" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -**Response:** -```json -[ - { - "id": 123456, - "name": "my-ssh-key", - "fingerprint": "aa:bb:cc:dd:ee:ff:11:22:33:44:55:66:77:88:99:00", - "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDe..." - } -] -``` - -## Hetzner Server Provisioning - -### 11. Create a Hetzner Server (Minimal Example) - -First, you need to get your private key UUID: - -```bash -curl -X GET "${COOLIFY_URL}/api/v1/security/keys" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" -``` - -Then create the server: - -```bash -curl -X POST "${COOLIFY_URL}/api/v1/servers/hetzner" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" \ - -d '{ - "cloud_provider_token_id": "abc123def456", - "location": "nbg1", - "server_type": "cx11", - "image": 67794396, - "private_key_uuid": "your-private-key-uuid" - }' -``` - -**Response:** -```json -{ - "uuid": "server-uuid-123", - "hetzner_server_id": 12345678, - "ip": "1.2.3.4" -} -``` - -### 12. Create a Hetzner Server (Full Example with All Options) - -```bash -curl -X POST "${COOLIFY_URL}/api/v1/servers/hetzner" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" \ - -d '{ - "cloud_provider_token_id": "abc123def456", - "location": "nbg1", - "server_type": "cx11", - "image": 67794396, - "name": "production-server", - "private_key_uuid": "your-private-key-uuid", - "enable_ipv4": true, - "enable_ipv6": true, - "hetzner_ssh_key_ids": [123456, 789012], - "cloud_init_script": "#cloud-config\npackages:\n - docker.io\n - git", - "instant_validate": true - }' -``` - -**Parameters:** -- `cloud_provider_token_id` (required): UUID of your Hetzner cloud provider token -- `location` (required): Hetzner location name (e.g., "nbg1", "fsn1", "hel1") -- `server_type` (required): Hetzner server type (e.g., "cx11", "cx21", "ccx13") -- `image` (required): Hetzner image ID (get from images endpoint) -- `name` (optional): Server name (auto-generated if not provided) -- `private_key_uuid` (required): UUID of the private key to use for SSH -- `enable_ipv4` (optional): Enable IPv4 (default: true) -- `enable_ipv6` (optional): Enable IPv6 (default: true) -- `hetzner_ssh_key_ids` (optional): Array of additional Hetzner SSH key IDs -- `cloud_init_script` (optional): Cloud-init YAML script for initial setup -- `instant_validate` (optional): Validate server connection immediately (default: false) - -## Complete Workflow Example - -Here's a complete example of creating a Hetzner server from start to finish: - -```bash -#!/bin/bash - -# Configuration -export COOLIFY_URL="http://localhost" -export API_TOKEN="root" -export HETZNER_API_TOKEN="your-hetzner-api-token" - -# Step 1: Create cloud provider token -echo "Creating cloud provider token..." -TOKEN_RESPONSE=$(curl -s -X POST "${COOLIFY_URL}/api/v1/cloud-tokens" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" \ - -d "{ - \"provider\": \"hetzner\", - \"token\": \"${HETZNER_API_TOKEN}\", - \"name\": \"My Hetzner Token\" - }") - -CLOUD_TOKEN_ID=$(echo $TOKEN_RESPONSE | jq -r '.uuid') -echo "Cloud token created: $CLOUD_TOKEN_ID" - -# Step 2: Get available locations -echo "Fetching locations..." -curl -s -X GET "${COOLIFY_URL}/api/v1/hetzner/locations?cloud_provider_token_id=${CLOUD_TOKEN_ID}" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" | jq '.[] | {name, description, country}' - -# Step 3: Get available server types -echo "Fetching server types..." -curl -s -X GET "${COOLIFY_URL}/api/v1/hetzner/server-types?cloud_provider_token_id=${CLOUD_TOKEN_ID}" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" | jq '.[] | {name, cores, memory, disk}' - -# Step 4: Get available images -echo "Fetching images..." -curl -s -X GET "${COOLIFY_URL}/api/v1/hetzner/images?cloud_provider_token_id=${CLOUD_TOKEN_ID}" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" | jq '.[] | {id, name, description}' - -# Step 5: Get private keys -echo "Fetching private keys..." -KEYS_RESPONSE=$(curl -s -X GET "${COOLIFY_URL}/api/v1/security/keys" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json") - -PRIVATE_KEY_UUID=$(echo $KEYS_RESPONSE | jq -r '.[0].uuid') -echo "Using private key: $PRIVATE_KEY_UUID" - -# Step 6: Create the server -echo "Creating server..." -SERVER_RESPONSE=$(curl -s -X POST "${COOLIFY_URL}/api/v1/servers/hetzner" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - -H "Content-Type: application/json" \ - -d "{ - \"cloud_provider_token_id\": \"${CLOUD_TOKEN_ID}\", - \"location\": \"nbg1\", - \"server_type\": \"cx11\", - \"image\": 67794396, - \"name\": \"my-production-server\", - \"private_key_uuid\": \"${PRIVATE_KEY_UUID}\", - \"enable_ipv4\": true, - \"enable_ipv6\": false, - \"instant_validate\": true - }") - -echo "Server created:" -echo $SERVER_RESPONSE | jq '.' - -SERVER_UUID=$(echo $SERVER_RESPONSE | jq -r '.uuid') -SERVER_IP=$(echo $SERVER_RESPONSE | jq -r '.ip') - -echo "Server UUID: $SERVER_UUID" -echo "Server IP: $SERVER_IP" -echo "You can now SSH to: root@$SERVER_IP" -``` - -## Error Handling - -### Common Errors - -**401 Unauthorized:** -```json -{ - "message": "Unauthenticated." -} -``` -Solution: Check your API token. - -**404 Not Found:** -```json -{ - "message": "Cloud provider token not found." -} -``` -Solution: Verify the UUID exists and belongs to your team. - -**422 Validation Error:** -```json -{ - "message": "Validation failed.", - "errors": { - "provider": ["The provider field is required."], - "token": ["The token field is required."] - } -} -``` -Solution: Check the request body for missing or invalid fields. - -**400 Bad Request:** -```json -{ - "message": "Invalid Hetzner token. Please check your API token." -} -``` -Solution: Verify your Hetzner API token is correct. - -## Testing with Yaak - -To import these examples into Yaak: - -1. Copy any curl command from this document -2. In Yaak, click "Import" → "From cURL" -3. Paste the curl command -4. Update the environment variables (COOLIFY_URL, API_TOKEN) in Yaak's environment settings - -Or create a Yaak environment with these variables: -```json -{ - "COOLIFY_URL": "http://localhost", - "API_TOKEN": "root" -} -``` - -Then you can use `{{COOLIFY_URL}}` and `{{API_TOKEN}}` in your requests. - -## Rate Limiting - -The Hetzner API has rate limits. If you receive a 429 error, the HetznerService will automatically retry with exponential backoff. The API token validation endpoints are also rate-limited on the Coolify side. - -## Security Notes - -- **Never commit your Hetzner API token** to version control -- Store API tokens securely in environment variables or secrets management -- Use the validation endpoint to test tokens before creating resources -- Cloud provider tokens are encrypted at rest in the database -- The actual token value is never returned by the API (only the UUID) diff --git a/docs/api/hetzner-yaak-collection.json b/docs/api/hetzner-yaak-collection.json deleted file mode 100644 index 13d1cf4a4..000000000 --- a/docs/api/hetzner-yaak-collection.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "name": "Coolify Hetzner Provisioning API", - "description": "Complete API collection for Hetzner server provisioning in Coolify", - "requests": [ - { - "name": "1. Create Hetzner Cloud Token", - "method": "POST", - "url": "{{COOLIFY_URL}}/api/v1/cloud-tokens", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ], - "body": { - "type": "json", - "content": "{\n \"provider\": \"hetzner\",\n \"token\": \"YOUR_HETZNER_API_TOKEN\",\n \"name\": \"My Hetzner Token\"\n}" - } - }, - { - "name": "2. List Cloud Provider Tokens", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/cloud-tokens", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "3. Get Cloud Provider Token", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/cloud-tokens/{{CLOUD_TOKEN_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "4. Update Cloud Token Name", - "method": "PATCH", - "url": "{{COOLIFY_URL}}/api/v1/cloud-tokens/{{CLOUD_TOKEN_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ], - "body": { - "type": "json", - "content": "{\n \"name\": \"Updated Token Name\"\n}" - } - }, - { - "name": "5. Validate Cloud Token", - "method": "POST", - "url": "{{COOLIFY_URL}}/api/v1/cloud-tokens/{{CLOUD_TOKEN_UUID}}/validate", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "6. Delete Cloud Token", - "method": "DELETE", - "url": "{{COOLIFY_URL}}/api/v1/cloud-tokens/{{CLOUD_TOKEN_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "7. Get Hetzner Locations", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/hetzner/locations?cloud_provider_token_id={{CLOUD_TOKEN_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "8. Get Hetzner Server Types", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/hetzner/server-types?cloud_provider_token_id={{CLOUD_TOKEN_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "9. Get Hetzner Images", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/hetzner/images?cloud_provider_token_id={{CLOUD_TOKEN_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "10. Get Hetzner SSH Keys", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/hetzner/ssh-keys?cloud_provider_token_id={{CLOUD_TOKEN_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "11. Get Private Keys (for server creation)", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/security/keys", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "12. Create Hetzner Server (Minimal)", - "method": "POST", - "url": "{{COOLIFY_URL}}/api/v1/servers/hetzner", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ], - "body": { - "type": "json", - "content": "{\n \"cloud_provider_token_id\": \"{{CLOUD_TOKEN_UUID}}\",\n \"location\": \"nbg1\",\n \"server_type\": \"cx11\",\n \"image\": 67794396,\n \"private_key_uuid\": \"{{PRIVATE_KEY_UUID}}\"\n}" - } - }, - { - "name": "13. Create Hetzner Server (Full Options)", - "method": "POST", - "url": "{{COOLIFY_URL}}/api/v1/servers/hetzner", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ], - "body": { - "type": "json", - "content": "{\n \"cloud_provider_token_id\": \"{{CLOUD_TOKEN_UUID}}\",\n \"location\": \"nbg1\",\n \"server_type\": \"cx11\",\n \"image\": 67794396,\n \"name\": \"my-server\",\n \"private_key_uuid\": \"{{PRIVATE_KEY_UUID}}\",\n \"enable_ipv4\": true,\n \"enable_ipv6\": false,\n \"hetzner_ssh_key_ids\": [],\n \"cloud_init_script\": \"#cloud-config\\npackages:\\n - docker.io\",\n \"instant_validate\": true\n}" - } - }, - { - "name": "14. Get Server Details", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/servers/{{SERVER_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "15. List All Servers", - "method": "GET", - "url": "{{COOLIFY_URL}}/api/v1/servers", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - }, - { - "name": "16. Delete Server", - "method": "DELETE", - "url": "{{COOLIFY_URL}}/api/v1/servers/{{SERVER_UUID}}", - "headers": [ - { - "name": "Authorization", - "value": "Bearer {{API_TOKEN}}" - }, - { - "name": "Content-Type", - "value": "application/json" - } - ] - } - ], - "environments": [ - { - "name": "Development", - "variables": { - "COOLIFY_URL": "http://localhost", - "API_TOKEN": "root", - "CLOUD_TOKEN_UUID": "", - "PRIVATE_KEY_UUID": "", - "SERVER_UUID": "" - } - }, - { - "name": "Production", - "variables": { - "COOLIFY_URL": "https://your-coolify-instance.com", - "API_TOKEN": "your-production-token", - "CLOUD_TOKEN_UUID": "", - "PRIVATE_KEY_UUID": "", - "SERVER_UUID": "" - } - } - ] -}