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 configurationcompose.prod.yml- Production overridesup -d- Start containers in detached mode--force-recreate- Force recreation even if configuration hasn't changedapi- 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
-
Always test in development first:
docker compose -f compose.yml -f compose.dev.yml up --build -
Monitor logs during deployment:
docker compose logs -f api -
Use specific image tags (not
latest):- Edit
compose.prod.ymlto pin versions - Example:
ghcr.io/oswatcher/graphql-api:v1.2.3
- Edit
-
Backup before major updates:
- See
scripts/neo4j-backup.shandscripts/minio-backup.sh
- See