Skip to content

Repository files navigation

GoBox

CI Release

Modular Go backend framework. Clean Architecture + DDD. Echo v5, Viper, gRPC, PostgreSQL, Redis, NATS, Kafka — all managed through a single CLI.


Requirements

Tool Version Installation
Go 1.22+ go.dev/dl
Docker 24+ docs.docker.com
Docker Compose v2+ Included with Docker Desktop
Task 3+ go install github.com/go-task/task/v3/cmd/task@latest
golang-migrate latest go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest
swag latest go install github.com/swaggo/swag/cmd/swag@latest

PATH Configuration

Add Go binaries to your PATH. Add to ~/.bashrc or ~/.zshrc:

export PATH="$HOME/go/bin:$PATH"

Reload: source ~/.bashrc


Quick Start

1. Install GoBox CLI

cd GoBox
go install ./cmd/gobox

Or through Taskfile:

task install

To install into /usr/local/bin:

task install-system

2. Create a new project

gobox new my-api
cd my-api

This generates a full project with Clean Architecture:

my-api/
├── cmd/api/main.go              # Entry point
├── internal/
│   ├── app/                     # Application bootstrap
│   ├── config/                  # Viper configuration
│   ├── domain/                  # Entities, value objects, repository interfaces
│   ├── usecase/                 # Business logic
│   ├── handler/                 # HTTP handlers (adapters)
│   ├── repository/              # Database implementations
│   ├── middleware/               # Security middleware
│   ├── module/                  # Module interface & registry
│   ├── modules/                 # Infrastructure modules
│   └── apperr/                  # Centralized error definitions
├── migrations/                  # SQL migrations
├── docker/                      # Dockerfile, PgBouncer config
├── certs/                       # JWT Ed25519 keys (generated)
├── docs/                        # Swagger/OpenAPI docs
├── docker-compose.yml           # Auto-generated per modules
├── gobox.yml                    # Project configuration
├── Taskfile.yml                 # Task runner commands
└── .env.example                 # Environment variables template

3. Configure and run

cp .env.example .env
task infra
task dev

Module Management

GoBox generates docker-compose.yml dynamically. Only enabled modules have containers — nothing extra runs.

Add a module

gobox add redis
gobox add nats
gobox add kafka
gobox add grpc
gobox add pgbouncer
gobox add cors
gobox add csrf
gobox add swagger
gobox add auth

Remove a module

gobox remove redis

Show version

gobox version

List modules

gobox list

Output:

Modules:
  * database
  * redis
    nats
    kafka
    grpc
    cors
    csrf
    pgbouncer
    auth
    swagger

* = enabled.


Available Modules

Infrastructure

Module Description Container
database PostgreSQL 16 via pgx postgres:16-alpine
redis Redis 7 with password + TLS support redis:7-alpine
nats NATS 2 messaging nats:2-alpine
kafka Kafka (KRaft, no Zookeeper) bitnami/kafka
grpc gRPC server with health check
pgbouncer Connection pooler for PostgreSQL edoburu/pgbouncer

Security

Module Description
cors Cross-Origin Resource Sharing
csrf Cross-Site Request Forgery protection

Features

Module Description
auth JWT authentication with Ed25519 keys, login/refresh endpoints, middleware
swagger Swagger/OpenAPI generation + Scalar UI

Auth Module

gobox add auth

This generates:

  • internal/handler/auth.go — Login & Refresh token endpoints
  • internal/middleware/jwt_auth.go — JWT Bearer middleware
  • migrations/000001_create_users.up.sql — Users table
  • certs/private.pem — Ed25519 private key (signing)
  • certs/public.pem — Ed25519 public key (verification)

Endpoints

Method Path Description
POST /auth/login Authenticate, returns access + refresh tokens
POST /auth/refresh Exchange refresh token for new access token

Protecting routes

import authMw "my-api/internal/middleware"

protected := e.Group("/api", authMw.JWTAuth(publicKey))
protected.GET("/profile", profileHandler)

Token format

  • Algorithm: Ed25519 (EdDSA)
  • Access token TTL: 24 hours
  • Refresh token TTL: 7 days

Swagger / Scalar

gobox add swagger
task swagger
  • Swagger JSON: http://localhost:8080/swagger/doc.json
  • Scalar UI: http://localhost:8080/scalar

To disable at runtime, set SWAGGER_ENABLED=false in .env.


Configuration

gobox.yml

name: my-api
server:
  host: "0.0.0.0"
  port: 8080
modules:
  - database
  - redis
  - grpc

.env

All settings are loaded via Viper with environment variable override.

# Server
SERVER_PORT=8080

# PostgreSQL
DATABASE_URL=postgres://gobox:gobox@localhost:5432/mydb?sslmode=disable
DATABASE_TLS=false

# PostgreSQL container
POSTGRES_USER=gobox
POSTGRES_PASSWORD=gobox
POSTGRES_DB=gobox

# PgBouncer
PGBOUNCER_ENABLED=false
PGBOUNCER_PORT=6432
PGBOUNCER_MAX_CONN=1000
PGBOUNCER_POOL_SIZE=25

# Redis
REDIS_URL=localhost:6379
REDIS_PASSWORD=mysecretpassword
REDIS_TLS=false

# NATS
NATS_URL=nats://localhost:4222

# Kafka
KAFKA_BROKERS=localhost:9092

# gRPC
GRPC_PORT=9090

# JWT
JWT_PRIVATE_KEY=certs/private.pem
JWT_PUBLIC_KEY=certs/public.pem

# Swagger
SWAGGER_ENABLED=true

TLS Support

PostgreSQL TLS

Set in .env:

DATABASE_URL=postgres://gobox:gobox@localhost:5432/mydb?sslmode=verify-full&sslrootcert=/path/to/ca.pem
DATABASE_TLS=true

Redis TLS

REDIS_TLS=true
REDIS_PASSWORD=your_redis_password

The Redis module will use TLS 1.2+ when REDIS_TLS=true.


Docker Compose

docker-compose.yml is auto-generated when you run gobox add or gobox remove. Only enabled modules get containers.

All passwords and ports come from .env:

cp .env.example .env
# Edit passwords in .env
task infra

PgBouncer

gobox add pgbouncer

Adds a connection pooler between your app and PostgreSQL. Default pool mode: transaction. Connect your app to port 6432 instead of 5432.


Database Migrations

# Run pending migrations
task migrate-up

# Rollback last migration
task migrate-down

# Create new migration
task migrate-create -- create_orders

Migration files go to migrations/ as raw SQL.


Task Commands

Command Description
task dev Start API server in development mode
task build Build API binary to bin/api
task build-cli Build GoBox CLI to bin/gobox
task install Install GoBox CLI globally
task install-system Install GoBox CLI to /usr/local/bin/gobox
task uninstall-system Remove GoBox CLI from /usr/local/bin/gobox
task infra Start Docker infrastructure
task infra-down Stop Docker infrastructure
task migrate-up Run database migrations
task migrate-down Rollback last migration
task migrate-create Create new migration file
task swagger Generate Swagger documentation
task test Run all tests
task lint Run golangci-lint

CI

GitHub Actions workflow: .github/workflows/ci.yml

Pipeline steps:

  • go mod download
  • golangci-lint
  • gofmt check
  • go vet ./...
  • go test ./...
  • go build ./...

If you rename the default branch or workflow file, update the badge link at the top of this README.


Release

GitHub Actions release workflow: .github/workflows/release.yml

When you push a tag like v0.1.0, GitHub Actions will build gobox for:

  • Linux amd64
  • Linux arm64
  • macOS amd64
  • macOS arm64
  • Windows amd64

Each artifact is attached to the GitHub Release and embeds version metadata visible through:

gobox version

Clean Architecture

Handler (HTTP/gRPC) → UseCase (Business Logic) → Repository (Database)
         ↑                    ↑                         ↑
    Adapters layer       Domain layer              Adapters layer

Domain layer (internal/domain/)

Entity structs and repository interfaces. No external dependencies.

type User struct {
    ID        string
    Email     string
    Password  string
    CreatedAt time.Time
}

type UserRepository interface {
    Create(ctx context.Context, user *User) error
    GetByID(ctx context.Context, id string) (*User, error)
}

UseCase layer (internal/usecase/)

Business logic. Depends only on domain interfaces.

type UserUseCase struct {
    repo domain.UserRepository
}

func (uc *UserUseCase) GetByID(ctx context.Context, id string) (*domain.User, error) {
    return uc.repo.GetByID(ctx, id)
}

Handler layer (internal/handler/)

HTTP handlers. Calls use cases, returns JSON.

Repository layer (internal/repository/)

Database implementations of domain repository interfaces.


Centralized Errors

All application errors are defined in internal/apperr/errors.go:

apperr.ErrNotFound
apperr.ErrUnauthorized
apperr.ErrForbidden
apperr.ErrValidation
apperr.ErrBadRequest
apperr.ErrConflict
apperr.ErrTimeout
apperr.ErrServiceDown
apperr.ErrInvalidToken
apperr.ErrExpiredToken
apperr.ErrDatabaseConn

Use in handlers:

if errors.Is(err, apperr.ErrNotFound) {
    return c.JSON(404, map[string]string{"error": "not found"})
}

Using Modules in Code

// PostgreSQL
dbMod := app.Module("database").(*database.Database)
db := dbMod.DB()

// Redis
redisMod := app.Module("redis").(*redis.Redis)
client := redisMod.Client()

// NATS
natsMod := app.Module("nats").(*nats.NATS)
conn := natsMod.Conn()

// Kafka
kafkaMod := app.Module("kafka").(*kafka.Kafka)
writer := kafkaMod.NewWriter("orders")
reader := kafkaMod.NewReader("orders", "consumer-group")

// gRPC
grpcMod := app.Module("grpc").(*grpc.GRPC)
pb.RegisterMyServiceServer(grpcMod.Server(), &myService{})

Project Health

GET /health returns status of all modules:

{
  "status": "ok",
  "modules": {
    "database": "ok",
    "redis": "ok"
  }
}

Tech Stack

Component Library Version
HTTP Router Echo v5.0.4
Configuration Viper v1.21.0
Database Driver pgx v5.9.1
Redis Client go-redis v9.18.0
Messaging nats.go v1.49.0
Streaming kafka-go v0.4.50
RPC gRPC v1.79.3
JWT golang-jwt v5.3.1
CLI Cobra v1.10.2
Logging slog stdlib

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages