A social knowledge tool for researchers built on ATProto

Deployment Guide#

This guide covers how to deploy the Annotations API service both locally for development and to production using fly.io.

Prerequisites#

Local Deployment#

Environment Setup#

  1. Clone the repository:

    git clone <repository-url>
    cd <repository-directory>
    
  2. Create environment files:

    cp .env.example .env.local
    
  3. Edit .env.local with your configuration:

    NODE_ENV=local
    
    # Database
    DB_HOST=localhost
    DB_PORT=5432
    DB_USERNAME=postgres
    DB_PASSWORD=postgres
    DB_NAME=annotations
    
    # Auth
    JWT_SECRET=your-local-secret-key
    ACCESS_TOKEN_EXPIRES_IN=3600
    REFRESH_TOKEN_EXPIRES_IN=2592000
    
    # ATProto
    ATPROTO_SERVICE_ENDPOINT=https://bsky.social
    ATPROTO_REDIRECT_URI=http://127.0.0.1:3000/api/users/oauth/callback
    
    # Server
    PORT=3000
    HOST=127.0.0.1
    

Using Docker Compose#

  1. Create a docker-compose.yml file:

    version: '3.8'
    
    services:
      app:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
          - '3000:3000'
        environment:
          - NODE_ENV=local
          - DB_HOST=db
          - DB_PORT=5432
          - DB_USERNAME=postgres
          - DB_PASSWORD=postgres
          - DB_NAME=annotations
        depends_on:
          - db
        volumes:
          - ./:/app
          - /app/node_modules
    
      db:
        image: postgres:14
        ports:
          - '5432:5432'
        environment:
          - POSTGRES_USER=postgres
          - POSTGRES_PASSWORD=postgres
          - POSTGRES_DB=annotations
        volumes:
          - postgres_data:/var/lib/postgresql/data
    
    volumes:
      postgres_data:
    
  2. Create a Dockerfile:

    FROM node:18-alpine
    
    WORKDIR /app
    
    COPY package*.json ./
    
    RUN npm install
    
    COPY . .
    
    RUN npm run build
    
    EXPOSE 3000
    
    CMD ["npm", "run", "start"]
    
  3. Start the services:

    docker-compose up -d
    
  4. Run migrations (if needed):

    docker-compose exec app npm run migrate
    
  5. Access the API at http://localhost:3000

Without Docker#

  1. Install dependencies:

    npm install
    
  2. Start a PostgreSQL database:

    docker run -d --name annotations-db \
      -e POSTGRES_USER=postgres \
      -e POSTGRES_PASSWORD=postgres \
      -e POSTGRES_DB=annotations \
      -p 5432:5432 \
      postgres:14
    
  3. Run migrations:

    npm run migrate
    
  4. Start the development server:

    npm run dev
    

Production Deployment with fly.io#

Setup#

  1. Install the flyctl CLI if you haven't already:

    curl -L https://fly.io/install.sh | sh
    
  2. Login to fly.io:

    fly auth login
    
  3. Create a fly.io app:

    fly apps create annotations-api
    
  4. Create a PostgreSQL database:

    fly postgres create --name annotations-db
    
  5. Attach the database to your app:

    fly postgres attach --app annotations-api annotations-db
    

Configuration#

  1. Create a fly.toml file:

    app = "annotations-api"
    primary_region = "iad"  # Choose your preferred region
    
    [build]
      dockerfile = "Dockerfile"
    
    [env]
      NODE_ENV = "prod"
      PORT = "8080"
      HOST = "0.0.0.0"
      ATPROTO_SERVICE_ENDPOINT = "https://bsky.social"
      ATPROTO_REDIRECT_URI = "https://your-app-url.fly.dev/api/users/oauth/callback"
    
    [http_service]
      internal_port = 8080
      force_https = true
      auto_stop_machines = true
      auto_start_machines = true
      min_machines_running = 1
      processes = ["app"]
    
  2. Set secrets:

    fly secrets set JWT_SECRET=your-production-secret-key \
      ACCESS_TOKEN_EXPIRES_IN=3600 \
      REFRESH_TOKEN_EXPIRES_IN=2592000
    
  3. Update the Dockerfile for production:

    FROM node:18-alpine AS builder
    
    WORKDIR /app
    
    COPY package*.json ./
    
    RUN npm ci
    
    COPY . .
    
    RUN npm run build
    
    # Production image
    FROM node:18-alpine
    
    WORKDIR /app
    
    COPY --from=builder /app/package*.json ./
    COPY --from=builder /app/dist ./dist
    
    RUN npm ci --only=production
    
    EXPOSE 8080
    
    CMD ["node", "dist/index.js"]
    

Deployment#

  1. Deploy the application:

    fly deploy
    
  2. Open your application:

    fly open
    

Scaling#

To scale your application:

fly scale count 2  # Adjust the number as needed

Monitoring#

Monitor your application:

fly status
fly logs

Environment Variables#

Variable Description Default
NODE_ENV Environment (local, dev, prod) local
DB_HOST Database host localhost
DB_PORT Database port 5432
DB_USERNAME Database username postgres
DB_PASSWORD Database password postgres
DB_NAME Database name annotations
DATABASE_URL Full database connection string -
JWT_SECRET Secret for JWT tokens default-secret-change-in-production
ACCESS_TOKEN_EXPIRES_IN Access token expiry in seconds 3600
REFRESH_TOKEN_EXPIRES_IN Refresh token expiry in seconds 2592000
ATPROTO_SERVICE_ENDPOINT AT Protocol service endpoint https://bsky.social
ATPROTO_REDIRECT_URI OAuth callback URL http://127.0.0.1:3000/api/users/oauth/callback
PORT Server port 3000
HOST Server host 127.0.0.1

Troubleshooting#

Database Connection Issues#

If you encounter database connection issues:

  1. Verify the database is running:

    docker ps  # For local Docker deployment
    fly postgres list  # For fly.io deployment
    
  2. Check connection parameters in environment variables.

  3. For fly.io, ensure the database is properly attached:

    fly postgres attach --app annotations-api annotations-db
    

Application Errors#

  1. Check application logs:

    docker-compose logs app  # For local Docker deployment
    fly logs  # For fly.io deployment
    
  2. Verify all required environment variables are set.

  3. For production issues, try redeploying:

    fly deploy