Deployment Procedures

August 21, 2026 · View on GitHub

This document describes the operational procedures for deploying updates to an OSWatcher production environment.

Prerequisites

Before deploying, ensure:

  • You have SSH access to your production server
  • The deployment directory contains this repository with a configured .env (see .env.example)
  • The API Docker image has been built and pushed to GHCR (via CI/CD)

Deployment Procedure: GraphQL API

Step 1: Connect to the Production Server

ssh <your-server>

Step 2: Navigate to the Deployment Directory

cd ~/oswatcher-deploy

Step 3: Pull and Recreate the API Container

docker compose -f compose.yml -f compose.prod.yml up -d --force-recreate api

What this does:

  • compose.yml - Base configuration
  • compose.prod.yml - Production overrides
  • up -d - Start containers in detached mode
  • --force-recreate - Force recreation even if configuration hasn't changed
  • api - Target only the API service (leaves Neo4j running)

Note: The OSWatcher images on GHCR are public and can be pulled anonymously. If you are deploying images from a private registry, authenticate first with docker login ghcr.io using a PAT with read:packages scope.

Step 4: Verify Deployment

# Check container status
docker compose ps

# View API logs
docker compose logs -f api

# Test API health endpoint (if available)
curl http://localhost:4000/health

Deployment Procedure: Frontend

The frontend has no pre-built image — compose.prod.yml builds it directly from the OSWatcher/frontend GitHub repo (master branch) at deploy time.

docker compose -f compose.yml -f compose.prod.yml up -d --build frontend

--build is required here (unlike the API) since there's no image to pull — Compose fetches the repo fresh and rebuilds.

Rollback Procedure

If the deployment fails or introduces issues:

# View available image tags
docker images ghcr.io/oswatcher/graphql-api

# Rollback to previous version
docker compose -f compose.yml -f compose.prod.yml down api
# Edit compose.prod.yml to specify previous image tag
docker compose -f compose.yml -f compose.prod.yml up -d api

Troubleshooting

Container Pull Failures

Problem: "Error response from daemon: pull access denied"

Solution:

  • Verify the image exists on GitHub Container Registry
  • Check image visibility (public vs private)
  • For private images, ensure you're authenticated: docker login ghcr.io

API Container Fails to Start

Problem: Container exits immediately after up

Solution:

# Check logs for error messages
docker compose logs api

# Common issues:
# - Database connection failure (check Neo4j is running)
# - Environment variable misconfiguration (check .env)
# - Port conflicts (check port 4000 availability)

Neo4j Connection Issues

Problem: API can't connect to Neo4j

Solution:

# Verify Neo4j is running
docker compose ps neo4j

# Check Neo4j logs
docker compose logs neo4j

# Test Neo4j connectivity
docker compose exec api nc -zv neo4j 7687

Best Practices

  1. Always test in development first:

    docker compose -f compose.yml -f compose.dev.yml up --build
    
  2. Monitor logs during deployment:

    docker compose logs -f api
    
  3. Use specific image tags (not latest):

    • Edit compose.prod.yml to pin versions
    • Example: ghcr.io/oswatcher/graphql-api:v1.2.3
  4. Backup before major updates:

    • See scripts/neo4j-backup.sh and scripts/minio-backup.sh