VacciChain maintains a production-equivalent staging environment for testing before production deployment.
- Network: Stellar Testnet (matches production configuration, uses testnet)
- Deployment: Automatic on merge to
main - URL: https://staging.vaccichain.example.com
- Infrastructure: AWS ECS Fargate (same as production)
- Secrets: AWS Secrets Manager (same as production)
┌─────────────────────────────────────────────────────────┐
│ Staging Environment │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Frontend │ │ Backend │ │ Python │ │
│ │ (nginx) │ │ (Express) │ │ (FastAPI) │ │
│ │ Port 80 │ │ Port 4000 │ │ Port 8001 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ └──────────────────┼──────────────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ AWS Secrets │ │
│ │ Manager │ │
│ └────────────────┘ │
│ │
│ ┌───────────────┐ │
│ │ Stellar │ │
│ │ Testnet │ │
│ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
- Code is pushed to
mainbranch - CI tests run (contract, backend, python, docker)
- On success,
deploy-staging.ymlworkflow triggers - Docker images are built and pushed to ECR
- ECS task definition is updated
- New containers are deployed to staging cluster
- Smoke tests verify deployment
- Deployment summary posted to GitHub
# Trigger deployment manually
gh workflow run deploy-staging.yml# Frontend
https://staging.vaccichain.example.com
# Backend API
https://staging.vaccichain.example.com/api
# Health check
curl https://staging.vaccichain.example.com/health- Connect Freighter wallet (set to Testnet)
- Request SEP-10 challenge:
POST /auth/sep10 - Sign challenge with wallet
- Verify signature:
POST /auth/verify - Receive JWT token
- Issue vaccination:
POST /vaccination/issue - Verify vaccination:
GET /verify/{wallet}
# From project root
npm run test:staging
# Or manually
curl -X POST https://staging.vaccichain.example.com/auth/sep10 \
-H "Content-Type: application/json" \
-d '{"account": "GAAAA..."}'# View backend logs
aws logs tail /ecs/vaccichain-staging --follow --filter-pattern "backend"
# View frontend logs
aws logs tail /ecs/vaccichain-staging --follow --filter-pattern "frontend"
# View python-service logs
aws logs tail /ecs/vaccichain-staging --follow --filter-pattern "python-service"# Check service status
aws ecs describe-services \
--cluster vaccichain-staging \
--services vaccichain-staging
# View task status
aws ecs list-tasks --cluster vaccichain-staging
aws ecs describe-tasks --cluster vaccichain-staging --tasks <task-arn>Staging uses the same AWS Secrets Manager setup as production:
# View staging secrets
aws secretsmanager describe-secret \
--secret-id vaccichain/staging/stellar
# Update staging secrets
aws secretsmanager update-secret \
--secret-id vaccichain/staging/stellar \
--secret-string '{...}'- Check GitHub Actions workflow logs
- Review ECS task logs:
aws logs tail /ecs/vaccichain-staging - Verify secrets exist in Secrets Manager
- Check IAM permissions for ECS task role
# Check service health
curl https://staging.vaccichain.example.com/health
# Check ECS task status
aws ecs describe-tasks \
--cluster vaccichain-staging \
--tasks $(aws ecs list-tasks --cluster vaccichain-staging --query 'taskArns[0]' --output text)
# View recent logs
aws logs tail /ecs/vaccichain-staging --follow --since 10m- Verify secret exists:
aws secretsmanager get-secret-value --secret-id vaccichain/staging/stellar - Check task role has permissions
- Review backend logs for auth errors
- Restart service:
aws ecs update-service --cluster vaccichain-staging --service vaccichain-staging --force-new-deployment
When staging is verified and ready:
- Create a release tag:
git tag v1.0.0 - Push tag:
git push origin v1.0.0 - Trigger production deployment:
gh workflow run deploy.yml -f network=mainnet - Monitor production deployment
Staging runs on:
- ECS Fargate: t3.small (0.25 vCPU, 512 MB) - ~$15/month
- ECR: ~$0.10/GB storage
- Secrets Manager: ~$0.40/secret/month
- CloudWatch Logs: ~$0.50/GB ingested
Total estimated cost: ~$20-30/month
To reduce costs:
- Scale down during off-hours
- Use spot instances for non-critical workloads
- Archive old logs to S3