Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lua.Nginx.Edge.Backend

A high-performance CRUD API backend built entirely in Lua embedded in Nginx via OpenResty, eliminating traditional application servers. Demonstrates edge computing where "the boundary between 'web server' and 'application server' is artificial."

OpenResty Lua PostgreSQL Docker License

Features

  • Zero Application Server - Pure Nginx + Lua, no Node.js/Python/Go runtime
  • PostgreSQL with Connection Pooling - Using pgmoon for async database access
  • JWT Authentication - Stateless auth with token blacklisting for logout
  • Three-Strategy Rate Limiting - Global IP, per-user, per-endpoint using lua-resty-limit-traffic
  • Input Validation & Security - SQL injection, XSS, path traversal, command injection detection
  • Response Caching with ETags - LRU cache with conditional requests (304 Not Modified)
  • Structured JSON Logging - Request/response logging with sanitization
  • Docker Compose Deployment - Production-ready with monitoring stack
  • Test::Nginx Integration Tests - Comprehensive API test suite

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        NGINX MASTER                              │
└──────────────────────────┬──────────────────────────────────────┘
                           │
        ┌──────────────────┼──────────────────┐
        ▼                  ▼                  ▼
┌───────────────┐  ┌───────────────┐  ┌───────────────┐
│  WORKER 1     │  │  WORKER 2     │  │  WORKER N     │
│  ┌─────────┐  │  │  ┌─────────┐  │  │  ┌─────────┐  │
│  │ Lua VM  │  │  │  │ Lua VM  │  │  │  │ Lua VM  │  │
│  │         │  │  │  │         │  │  │  │         │  │
│  │Router   │  │  │  │Router   │  │  │  │Router   │  │
│  │Middleware│ │  │  │Middleware│ │  │  │Middleware│ │
│  │Handlers │  │  │  │Handlers │  │  │  │Handlers │  │
│  │DB Pool  │  │  │  │DB Pool  │  │  │  │DB Pool  │  │
│  │Cache    │  │  │  │Cache    │  │  │  │Cache    │  │
│  └─────────┘  │  │  └─────────┘  │  │  └─────────┘  │
└───────────────┘  └───────────────┘  └───────────────┘
        │                  │                  │
        └──────────────────┼──────────────────┘
                           ▼
              ┌─────────────────────────┐
              │     POSTGRESQL          │
              │   (Connection Pool)     │
              └─────────────────────────┘

Quick Start

Prerequisites

  • Docker & Docker Compose
  • Git

Development

# Clone the repository
git clone https://github.com/YOUR_USERNAME/lua-nginx-edge-backend.git
cd lua-nginx-edge-backend

# Start all services
docker compose -f docker/docker-compose.yml up -d

# View logs
docker compose -f docker/docker-compose.yml logs -f openresty

# Run tests
docker compose -f docker/docker-compose.yml exec openresty prove -I /usr/local/openresty/site/lib/perl5 tests/integration.t

Production Deployment

# Set required environment variables
export JWT_SECRET="your-super-secret-jwt-key-min-32-chars"

# Deploy
docker compose -f docker/docker-compose.yml up -d --build

# Scale workers
docker compose -f docker/docker-compose.yml up -d --scale openresty=3

API Endpoints

Authentication

Method Endpoint Description
POST /api/v1/auth/register Register new user
POST /api/v1/auth/login Login and get JWT token
POST /api/v1/auth/refresh Refresh JWT token
POST /api/v1/auth/logout Logout (blacklist token)
GET /api/v1/auth/me Get current user info

Items (Protected)

Method Endpoint Description
GET /api/v1/items List items (paginated, filterable)
POST /api/v1/items Create new item
GET /api/v1/items/:id Get single item
PUT /api/v1/items/:id Full update item
PATCH /api/v1/items/:id Partial update item
DELETE /api/v1/items/:id Delete item

Users (Protected)

Method Endpoint Description
GET /api/v1/users/me Get current user profile
PUT /api/v1/users/me Update profile
PUT /api/v1/users/me/password Change password
GET /api/v1/users List users (admin)
GET /api/v1/users/:id Get user by ID (admin)
DELETE /api/v1/users/:id Delete user (admin)

System

Method Endpoint Description
GET /health Health check
GET /metrics Prometheus metrics

Usage Examples

Register & Login

# Register
curl -X POST http://localhost:8080/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"username": "johndoe", "email": "john@example.com", "password": "SecurePass123!"}'

# Login
curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "john@example.com", "password": "SecurePass123!"}'

# Response: {"success":true,"data":{"user":{...},"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}}

CRUD Operations

# Set token
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

# Create item
curl -X POST http://localhost:8080/api/v1/items \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "My Item", "description": "Description", "metadata": {"tags": ["tag1", "tag2"]}}'

# List items with pagination
curl -X GET "http://localhost:8080/api/v1/items?page=1&per_page=10" \
  -H "Authorization: Bearer $TOKEN"

# Get single item
curl -X GET http://localhost:8080/api/v1/items/1 \
  -H "Authorization: Bearer $TOKEN"

# Update item
curl -X PUT http://localhost:8080/api/v1/items/1 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "Updated Title"}'

# Delete item
curl -X DELETE http://localhost:8080/api/v1/items/1 \
  -H "Authorization: Bearer $TOKEN"

Rate Limit Headers

All responses include rate limit headers:

X-RateLimit-Limit-Global: 100
X-RateLimit-Remaining-Global: 99
X-RateLimit-Reset-Global: 1699999999
X-RateLimit-Limit-User: 1000
X-RateLimit-Remaining-User: 999
X-RateLimit-Reset-User: 1699999999
X-RateLimit-Limit-Endpoint: 50
X-RateLimit-Remaining-Endpoint: 49
X-RateLimit-Reset-Endpoint: 1699999999

ETag Caching

# First request - returns ETag
curl -I http://localhost:8080/api/v1/items -H "Authorization: Bearer $TOKEN"
# ETag: "a1b2c3d4e5f6..."

# Conditional request - returns 304 if unchanged
curl -I http://localhost:8080/api/v1/items \
  -H "Authorization: Bearer $TOKEN" \
  -H 'If-None-Match: "a1b2c3d4e5f6..."'

Configuration

Environment Variables

Variable Default Description
DB_HOST postgres PostgreSQL host
DB_PORT 5432 PostgreSQL port
DB_NAME edge_backend Database name
DB_USER edge_user Database user
DB_PASSWORD edge_pass Database password
DB_POOL_SIZE 10 Connection pool size per worker
DB_TIMEOUT 5000 Query timeout (ms)
JWT_SECRET required JWT signing secret (min 32 chars)
JWT_EXPIRES_IN 3600 Token expiry (seconds)
NGINX_WORKER_PROCESSES auto Nginx worker processes
NGINX_WORKER_CONNECTIONS 1024 Connections per worker

Rate Limiting Configuration

Configure in nginx/nginx.conf (init_by_lua_block):

_G.rate_limit_config = {
    global = { window = 60, limit = 100 },      -- 100 req/min per IP
    user = { window = 60, limit = 1000 },       -- 1000 req/min per user
    endpoint = { window = 60, limit = 50 },     -- 50 req/min per endpoint per IP
}

Project Structure

lua-nginx-edge-backend/
├── docker/
│   ├── Dockerfile.openresty      # Multi-stage OpenResty build
│   ├── docker-compose.yml        # Full stack deployment
│   └── init-db/
│       └── 01-schema.sql         # Database schema
├── lua/
│   ├── handlers/                 # Route handlers
│   │   ├── auth.lua              # Authentication endpoints
│   │   ├── items.lua             # Items CRUD
│   │   └── users.lua             # User management
│   ├── middleware/               # Request/response middleware
│   │   ├── jwt_auth.lua          # JWT validation
│   │   ├── rate_limit.lua        # Three-strategy rate limiting
│   │   ├── validate.lua          # Input validation
│   │   └── logging.lua           # Structured logging
│   ├── utils/                    # Shared utilities
│   │   ├── response.lua          # API response formatting
│   │   ├── database.lua          # PostgreSQL connection pool
│   │   ├── validate.lua          # Validation helpers
│   │   └── jwt.lua               # JWT token management
│   └── router.lua                # Main request router
├── nginx/
│   └── nginx.conf                # OpenResty configuration
├── tests/
│   ├── integration.t             # Test::Nginx integration tests
│   └── unit/
│       └── test_validate.lua     # Busted unit tests
├── docs/
│   └── api.md                    # Detailed API documentation
├── scripts/
│   └── deploy.sh                 # Deployment helper
├── .gitignore
├── LICENSE
└── README.md

Monitoring Stack

The Docker Compose includes:

  • Prometheus (port 9090) - Metrics collection
  • Grafana (port 3000) - Dashboards (admin/admin)
  • Loki (port 3100) - Log aggregation
  • Promtail - Log shipping to Loki

Access Grafana at http://localhost:3000 with default credentials admin/admin.

Testing

Integration Tests (Test::Nginx)

# Run all integration tests
docker compose -f docker/docker-compose.yml exec openresty prove tests/integration.t

# Run with verbose output
docker compose -f docker/docker-compose.yml exec openresty prove -v tests/integration.t

Unit Tests (Busted)

# Install busted
luarocks install busted

# Run unit tests
busted tests/unit/

Load Testing

# Install hey
go install github.com/rakyll/hey@latest

# Load test
hey -n 10000 -c 100 -H "Authorization: Bearer $TOKEN" http://localhost:8080/api/v1/items

Security Considerations

  1. Change Default Secrets - Set JWT_SECRET to a strong random value (32+ chars)
  2. Use HTTPS - Terminate TLS at load balancer or configure Nginx SSL
  3. Database Passwords - Use Docker secrets or external secret management
  4. Rate Limiting - Adjust limits based on your traffic patterns
  5. Input Validation - All inputs sanitized; SQL injection/XSS patterns blocked
  6. Security Headers - CSP, X-Frame-Options, HSTS included
  7. Token Blacklisting - Logout invalidates tokens immediately

Performance Tuning

Nginx Workers

worker_processes auto;  # Uses all CPU cores
worker_connections 1024;  # Per worker

LuaJIT

OpenResty uses LuaJIT 2.1 for maximum performance. Ensure:

  • lua_code_cache on in production (default)
  • Pre-load modules in init_by_lua_block

Database Connection Pool

_G.db_config.pool_size = 10  -- Per worker
-- Total connections = workers * pool_size

Caching

-- Response cache (per worker)
local cache, err = lrucache.new(10000)  -- 10k entries

Contributing

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open Pull Request

License

MIT License - see LICENSE for details.

Acknowledgments


Built with ❤️ using OpenResty and Lua

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages