internal/website/docs/guides/cli-gateway.md
The Go Micro CLI provides two gateway modes for accessing your microservices: development (micro run) and production (micro server). Both use the same underlying gateway architecture, ensuring consistent behavior across environments.
┌─────────────────────┐
│ HTTP Requests │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Unified Gateway │
│ │
│ • Service Discovery│
│ • HTTP → RPC │
│ • Web Dashboard │
│ • Health Checks │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Your Services │
│ (via Registry) │
└─────────────────────┘
| Feature | micro run | micro server |
|---|---|---|
| Purpose | Local development | Production API gateway |
| Authentication | Yes (default admin/micro) | Yes (default admin/micro) |
| Process Management | Yes (builds & runs services) | No (services run separately) |
| Hot Reload | Yes (watches file changes) | No |
| Endpoint Scopes | Yes (/auth/scopes) | Yes (/auth/scopes) |
| Best For | Coding, testing, iteration | Deployed environments |
micro run# Create and run a service
micro new myservice
cd myservice
micro run
Open http://localhost:8080 - no login required!
/api/{service}/{method}/admin/micro)/auth/scopes# Start with hot reload
micro run
# Log in at http://localhost:8080 with admin/micro
# Or use a token for API calls:
curl -X POST http://localhost:8080/api/myservice/Handler.Call \
-H "Authorization: Bearer <token>" \
-d '{"name": "World"}'
See micro run guide for full details.
micro server# Start your services separately (e.g., via systemd, docker)
./myservice &
# Start the gateway
micro server --address :8080
Open http://localhost:8080 and log in with admin/micro.
All API calls require an Authorization header:
# Get a token (via web UI or login endpoint)
TOKEN="eyJhbGc..."
# Call a service with auth
curl -X POST http://localhost:8080/api/myservice/Handler.Call \
-H "Authorization: Bearer $TOKEN" \
-d '{"name": "World"}'
admin/micro/auth/tokens → Generate token with scopes/auth/scopes → Restrict which endpoints require which scopesAuthorization: Bearer <token> headerBoth commands provide the same core gateway capabilities:
The gateway automatically converts HTTP requests to RPC calls:
POST /api/{service}/{method}
Content-Type: application/json
{"field": "value"}
Becomes an RPC call to:
{service}{method}{"field": "value"}The gateway queries the registry (mdns, consul, etcd) to find services:
# List all services
curl http://localhost:8080/services
# Returns:
[
{"name": "myservice", "endpoints": ["Handler.Call", "Handler.List"]},
{"name": "users", "endpoints": ["Users.Create", "Users.Get"]}
]
Services register automatically when they start - no manual configuration needed!
Visit / in your browser to:
# Aggregate health of all services
curl http://localhost:8080/health
# Kubernetes-style probes
curl http://localhost:8080/health/live # Is gateway alive?
curl http://localhost:8080/health/ready # Are services ready?
The gateway automatically picks up:
No gateway restart needed!
Scopes provide fine-grained access control over which tokens can call which endpoints. Both micro run and micro server support scopes.
Set up endpoint scopes:
/auth/scopes to see all discovered endpointsbilling on payments.Payments.Charge)greeter.*)Create scoped tokens:
/auth/tokens and create a token with matching scopesbilling can call endpoints that require billing* bypasses all scope checksScopes are enforced on all call paths:
/api/{service}/{endpoint})/api/mcp/call)The gateway uses auth.Account from the go-micro framework. The account's Scopes field carries the same []string used by the framework's wrapper/auth package for service-level auth.
Previously, micro run and micro server had separate gateway implementations. This caused:
The unified gateway means:
From a user perspective:
micro run and micro server both have auth enabledThe unification is internal - your code keeps working.
# 1. Develop locally without auth
micro run
# Test: curl http://localhost:8080/api/...
# 2. Build for production
go build -o myservice
# 3. Deploy services
./myservice & # or via systemd, docker, k8s
# 4. Start gateway with auth
micro server
# 5. Generate API token (via web UI)
# Use token in production API calls
# micro.mu
service api
path ./api
port 8081
service worker
path ./worker
port 8082
depends api
service web
path ./web
port 8090
depends api worker
# Start all with gateway
micro run
See micro run guide for configuration details.
Deploy micro server as your API gateway in front of all services:
Internet
│
┌───────▼────────┐
│ micro server │ :8080 (public)
│ + JWT Auth │
└───────┬────────┘
│
┌───────────┼───────────┐
│ │ │
┌───▼───┐ ┌──▼───┐ ┌──▼────┐
│ users │ │ posts│ │comments│
│ :8081 │ │ :8082│ │ :8083 │
└───────┘ └──────┘ └────────┘
(internal) (internal) (internal)
Only micro server needs public access - services can be internal.
You can also use the gateway in your own Go code:
package main
import (
"context"
"log"
"go-micro.dev/v5/cmd/micro/server"
"go-micro.dev/v5/store"
)
func main() {
// Start gateway with custom options
gw, err := server.StartGateway(server.GatewayOptions{
Address: ":9000",
AuthEnabled: true, // Enable authentication
Store: store.DefaultStore,
Context: context.Background(),
})
if err != nil {
log.Fatal(err)
}
log.Printf("Gateway running on %s", gw.Addr())
// Block until context is cancelled
gw.Wait()
}
This gives you full control over gateway configuration in custom deployments.
Problem: http://localhost:8080 shows empty service list
Solution:
ps aux | grep myservice~/micro/logs/ for service startup errorsProblem: curl http://localhost:8080/api/myservice/Handler.Call returns 404
Solution:
Handler.Call vs handler.callmicro services or check web UIProblem: API returns 401 Unauthorized
Solution:
Authorization: Bearer <token>Problem: API returns 403 Forbidden with insufficient scopes
Solution:
/auth/scopes/auth/tokens)* scope for full accessProblem: micro run or micro server won't start
Solution:
# Check what's using port 8080
lsof -i :8080
# Use different port
micro run --address :9000
micro server --address :9000