Skip to main content

Initial Setup - API

This guide provides comprehensive instructions for setting up the API service for the first time, including server configuration, Nginx reverse proxy setup with path-based routing, and environment configuration.

Prerequisites

Before beginning the setup process, ensure you have:

  • Virtual Machine: 1 VM with a public IP address
  • Security Group Configuration: Ports 22 (SSH), 80 (HTTP), and 443 (HTTPS) must be open
  • SSL Certificates: Valid SSL certificate files (certificate.crt and private.key)
  • Domain Name: Domain name configured to point to the VM's public IP
  • GitHub Repository Access: Access to configure secret environments
  • Docker Knowledge: Basic understanding of Docker and Docker Compose
  • API Service Information: Container name, internal port, and URL path prefix for the API service

Step 1: Server Preparation

1.1 Connect to the Server

SSH into your virtual machine using your credentials:

ssh user@your-server-ip

1.2 Install Docker Engine

Install Docker Engine on Ubuntu by following the official Docker documentation:

# Visit and follow instructions from:
# https://docs.docker.com/engine/install/ubuntu/
Quick Install

For Ubuntu, you can use the convenience script:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

After adding your user to the docker group, log out and log back in for the changes to take effect.

1.3 Verify Docker Installation

Verify that Docker is installed correctly:

docker --version
docker compose version

Step 2: Nginx Reverse Proxy Setup

The API service will be served through an Nginx reverse proxy container to handle SSL termination and path-based routing.

2.1 Create Nginx Directory Structure

Create the necessary directory structure for Nginx configuration:

mkdir -p nginx/certs
cd nginx

2.2 Add SSL Certificates

Place your SSL certificate files in the certs directory:

# Copy your SSL certificate files
cp /path/to/your/certificate.crt ./certs/certificate.crt
cp /path/to/your/private.key ./certs/private.key

# Set appropriate permissions
chmod 644 ./certs/certificate.crt
chmod 600 ./certs/private.key
Security

Ensure that private key files have restricted permissions (600) to prevent unauthorized access.

2.3 Create Docker Compose File

Create a docker-compose.yaml or compose.yaml file with the following configuration:

services:
nginx:
image: nginx:1.25-alpine
container_name: nginx-api
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./certs/certificate.crt:/etc/nginx/certs/certificate.crt:ro
- ./certs/private.key:/etc/nginx/certs/private.key:ro
networks:
- sbmcrm-network
healthcheck:
test: ["CMD", "nginx", "-t"]
interval: 30s
timeout: 10s
retries: 3

networks:
sbmcrm-network:
external: true
Network Configuration

The sbmcrm-network must be created before starting the containers. Create it with:

docker network create sbmcrm-network

2.4 Create Nginx Configuration

Create an nginx.conf file with the following configuration. This configuration includes path-based routing, which is essential for API services:

# Upstream configuration for API service
upstream api-service {
server api-container:8080;
}

# HTTP (Port 80) Server Block - Redirect to HTTPS
server {
listen 80;
listen [::]:80;

server_name api.example.com;
server_tokens off;

# Redirect all HTTP traffic to HTTPS
return 301 https://$host$request_uri;
}

# HTTPS (Port 443) Server Block
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;

server_name api.example.com;

# Client upload size limit
client_max_body_size 500m;

# SSL Certificate Configuration
ssl_certificate /etc/nginx/certs/certificate.crt;
ssl_certificate_key /etc/nginx/certs/private.key;

# Recommended TLS Settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1h;
ssl_session_tickets off;

# Security Headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

# API Location Block with Path Stripping
# This location block handles requests to /api/v1/ and strips the prefix
location /api/v1/ {
resolver 127.0.0.11 valid=30s;

# Strip the /api/v1/ prefix before proxying
rewrite ^/api/v1/(.*)$ /$1 break;

# Proxy to the API service upstream
proxy_pass http://api-service;

# HTTP Version and WebSocket Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $http_host;

# Forward Client Information
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;

# Cookie Forwarding
proxy_pass_header Set-Cookie;
proxy_set_header Cookie $http_cookie;

# Timeout Settings
proxy_read_timeout 300s;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
send_timeout 300s;

# Cache Bypass for WebSocket
proxy_cache_bypass $http_upgrade;
}

# Health Check Endpoint (optional)
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
Configuration Variables

Replace the following placeholders in the configuration:

  • api.example.com: Your actual domain name
  • api-service: The upstream name (can be any identifier)
  • api-container: The Docker container name for the API service
  • 8080: The internal port the API service listens on (adjust if different)
  • /api/v1/: The URL path prefix for your API (adjust based on your API structure)
Path Stripping

The rewrite ^/api/v1/(.*)$ /$1 break; directive strips the /api/v1/ prefix from the request before forwarding it to the backend. This allows your API to receive requests without the path prefix, while external clients access it with the prefix.

2.5 Start Nginx Container

Start the Nginx reverse proxy:

docker compose up -d

Verify that the container is running:

docker ps
docker logs nginx-api

2.6 Test Nginx Configuration

Test the Nginx configuration for syntax errors:

docker exec nginx-api nginx -t

Step 3: Configure Secret Environments

Configure the required secret environment variables in your GitHub repository.

3.1 Access GitHub Repository Settings

  1. Navigate to your GitHub repository
  2. Click on Settings in the repository menu
  3. Navigate to Environments in the left sidebar

3.2 Configure Environment Secrets

Create or update the environment (e.g., staging, production) and add the following secrets:

  • Database Connection Strings: PostgreSQL connection details
  • Redis Connection Strings: Redis cache connection details
  • JWT Secrets: Authentication token secrets
  • API Keys: External service API keys
  • Encryption Keys: Data encryption keys
  • Third-party Service Credentials: Any required service credentials (payment gateways, SMS services, etc.)
Required Secrets

The exact list of required secrets depends on your API configuration. Common secrets include:

  • DATABASE_URL: PostgreSQL connection string
  • REDIS_URL: Redis connection string
  • JWT_SECRET: JWT token signing secret
  • ENCRYPTION_KEY: Data encryption key
  • API_KEYS: External service API keys

3.3 Verify Secret Configuration

Ensure all required secrets are properly configured and accessible to your CI/CD pipeline.

Step 4: Adding Additional API Services

When you need to add additional API modules or services to the same server, you can extend the Nginx configuration:

4.1 Add New Upstream

Add a new upstream block for the additional service:

upstream new-api-service {
server new-api-container:8080;
}

4.2 Add New Location Block

Add a new location block within the HTTPS server block:

location /api/v2/ {
resolver 127.0.0.11 valid=30s;
rewrite ^/api/v2/(.*)$ /$1 break;
proxy_pass http://new-api-service;

# ... (same proxy settings as above)
}

4.3 Reload Nginx

After making changes, reload Nginx configuration:

docker exec nginx-api nginx -s reload

Or restart the container:

cd nginx
docker compose restart

Step 5: Verify Setup

5.1 Check Container Status

Verify all containers are running:

docker ps

You should see:

  • nginx-api container running
  • API service container(s) running (if already deployed)

5.2 Test HTTPS Access

Test access to the API via HTTPS:

# Test the API endpoint
curl -I https://api.example.com/api/v1/health

# Test with a sample request
curl -X GET https://api.example.com/api/v1/endpoint

5.3 Verify Path Routing

Verify that path-based routing works correctly:

# This should route to your API service
curl https://api.example.com/api/v1/users

# Verify the path is correctly stripped
# Check API logs to confirm the request arrives without /api/v1/ prefix

5.4 Verify SSL Certificate

Verify that SSL is properly configured:

openssl s_client -connect api.example.com:443 -servername api.example.com

5.5 Check Nginx Logs

Monitor Nginx logs for any errors:

docker logs -f nginx-api

Troubleshooting

Common Issues

Nginx container fails to start

  • Verify Docker network exists: docker network ls
  • Check if ports 80 and 443 are already in use: sudo netstat -tulpn | grep -E ':(80|443)'
  • Verify SSL certificate paths and permissions

502 Bad Gateway errors

  • Verify the API container is running: docker ps
  • Check if the container name and port in nginx.conf match the actual service
  • Verify Docker network connectivity: docker network inspect sbmcrm-network
  • Check API service logs: docker logs <api-container-name>

Path routing not working

  • Verify the rewrite directive is correctly configured
  • Check that the location block path matches your API path prefix
  • Test with curl -v to see the full request/response headers
  • Verify the API service is receiving requests without the path prefix

SSL certificate errors

  • Ensure certificate files are in the correct format (PEM)
  • Verify certificate and key match: openssl x509 -noout -modulus -in certs/certificate.crt | openssl md5 and openssl rsa -noout -modulus -in certs/private.key | openssl md5
  • Check certificate expiration: openssl x509 -in certs/certificate.crt -noout -dates

Connection timeouts

  • Verify firewall rules allow traffic on ports 80 and 443
  • Check security group settings in your cloud provider
  • Verify domain DNS points to the correct IP address
  • Check API service health: docker logs <api-container-name>

CORS issues

  • Ensure your API service handles CORS headers correctly
  • Verify Nginx is not interfering with CORS headers
  • Check browser console for specific CORS error messages

Next Steps

After completing the initial setup:

  1. Deploy the API Service: Follow the API Deployment Guide to deploy your first version
  2. Add Additional Services: Use the process described in Step 4 to add more API modules
  3. Configure Monitoring: Set up monitoring and logging as described in the Monitoring Setup Guide
  4. Review Security: Review and implement additional security measures from the SSL Security Guide