Deployment Quick Start Guide

Last updated: February 8, 2026
Admin Tools

Deployment Quick Start Guide

Welcome! 👋

This guide will help you learn the Sampo deployment system in ~30 minutes. You'll deploy your first change to production safely and confidently.

Prerequisites Checklist

Before starting, make sure you have:

  • [ ] SSH access to VPS (ssh root@23.235.204.208 works)
  • [ ] Docker Desktop installed and running
  • [ ] Git repository cloned and up to date
  • [ ] .env.blueline-alpha file in project root
  • [ ] pnpm installed (pnpm -v works)

Don't have these? Ask DevOps team for access.


Your First Deployment (Tutorial)

We'll make a small, safe change and deploy it to production. This is the safest way to learn!

Step 1: Make a Small Change (2 minutes) ⚠️ REQUIRED

You MUST make this change - the verification step checks for it!

Open the health controller:

# Open the health controller
code apps/api/src/health/health.controller.ts

Find the @Get() method (around line 38) and add YOUR comment with YOUR actual name:

@Public()
@Get()
// ... other decorators ...
getHealth() {
  // DEPLOYMENT TEST: Mark Jedrzejczyk - 2026-02-08
  // ⬆️ REPLACE with YOUR name and TODAY'S date!
  return this.healthService.getBasicHealth();
}

Example (use YOUR name and date):

// DEPLOYMENT TEST: Jane Smith - 2026-02-08
// DEPLOYMENT TEST: John Doe - 2026-02-08
// DEPLOYMENT TEST: Your Name Here - 2026-02-08

⚠️ CRITICAL: Replace <Your Name> and <Today's Date> with actual values, not the placeholders!

Why this change?

  • It's safe (just a comment, no behavior change)
  • It's traceable (you can verify YOUR change deployed by finding YOUR name on VPS)
  • It's reversible (easy to rollback if needed)

Save the file after making this change!

Step 2: Validate Locally (3 minutes)

Before deploying, always validate:

# 1. Validate environment
./scripts/validate-deployment-env.sh

# Expected: "✅ All environment variables validated successfully"

If validation fails:

  • Check .env.blueline-alpha exists
  • Verify all required variables are set
  • Ask team if unsure about any values
# 2. Type check
pnpm type-check

# Expected: "No errors found"

If type errors:

  • These are from your change (fix them)
  • OR from main branch (pull latest and fix)
# 3. Verify YOUR change is in the file
grep -i "DEPLOYMENT TEST.*$(whoami)" apps/api/src/modules/health/health.controller.ts

# Expected: Shows YOUR comment line
# Example: // DEPLOYMENT TEST: Mark Jedrzejczyk - 2026-02-08

If grep finds NOTHING:

  • ⚠️ STOP! You skipped Step 1
  • Go back and add YOUR comment to the TypeScript file
  • Don't proceed until you see your name in the grep output

Step 3: Dry-Run (Preview) (2 minutes)

Let's see what would happen without actually deploying:

./scripts/docker-audit/build-cross-platform.sh --all --amd64 \
  --api-url https://alpha.theblueline.com/api \
  --push root@23.235.204.208 \
  --dry-run

What to look for in output:

  • ✅ Version tag (e.g., 20260208-143022-a4c6788)
  • ✅ Two images: API and Web
  • ✅ Estimated transfer size (~1.15GB)
  • ✅ Deployment steps listed

This is safe - nothing is deployed, just a preview.

Step 4: Deploy for Real (10-15 minutes)

Now let's actually deploy:

./scripts/docker-audit/build-cross-platform.sh --all --amd64 \
  --api-url https://alpha.theblueline.com/api \
  --push root@23.235.204.208 \
  --smoke-tests

What's happening (watch the output):

  1. Environment Validation (~5 seconds)

    • Checks 8 required variables
  2. Type Check (~10 seconds)

    • Validates TypeScript
  3. Build API Image (~2-4 minutes)

    • Watch for cache hits (faster builds)
    • Look for "CACHED" vs "RUN" lines
  4. Build Web Image (~4-7 minutes)

    • Next.js build is slowest part
  5. Container Smoke Tests (~30 seconds)

    • Verifies containers can start
  6. Transfer Images (~2-3 minutes)

    • Uploads to VPS over SSH
    • Loads images into Docker
  7. Deployment Smoke Tests (~30 seconds)

    • Runs 6 automated checks

Total time: 10-15 minutes (depends on cache)

⚠️ CRITICAL: Images are transferred but containers NOT restarted automatically

Step 4b: Restart Containers (1 minute)

The build script transfers images but doesn't restart containers. You must do this manually:

ssh root@23.235.204.208 << 'REMOTE'
  cd /opt/sampo-alpha

  # Stop old containers
  docker compose -f docker-compose.base.yml \
    -f docker-compose.blueline-alpha.override.yml down

  # Start new containers with fresh images
  docker compose -f docker-compose.base.yml \
    -f docker-compose.blueline-alpha.override.yml up -d

  # Wait for healthy status
  sleep 15

  # Verify containers started
  docker ps --filter "name=blueline-alpha"
REMOTE

Expected output:

  • All 3 containers: Up X seconds (healthy)
  • NOT "Up X hours" (that means old containers still running!)

Step 5: Verify Deployment Version (1 minute)

Method 1: Visual Check (Fastest)

Navigate to Admin Dashboard:

https://alpha.theblueline.com/admin/dashboard

Look for the build version badge in the top-right corner:

🔖 2131d0c • 2026-02-08

Hover over it to see full details:

  • Deployed date and time (UTC)
  • Git commit SHA
  • Full version string

If the commit SHA matches your build ✅ → Deployment succeeded!

Method 2: API Check (Programmatic)

curl -s https://alpha.theblueline.com/health | jq -r '.buildVersion'

Expected output:

20260208-175451-2131d0c

This is your deployment version - it changes with every build!

Format: YYYYMMDD-HHMMSS-GITSHA

  • 20260208 = February 8, 2026 (today)
  • 175451 = 5:54:51 PM (when you built)
  • 2131d0c = Git commit (first 7 characters)

How to use it:

Verify deployment worked:

# Save version from build output
BUILD_VERSION="20260208-175451-2131d0c"

# Check if it's running
RUNNING_VERSION=$(curl -s https://alpha.theblueline.com/health | jq -r '.buildVersion')

if [ "$RUNNING_VERSION" = "$BUILD_VERSION" ]; then
  echo "✅ Correct version deployed!"
else
  echo "❌ Wrong version! Running: $RUNNING_VERSION, Expected: $BUILD_VERSION"
fi

If version is wrong:

  • ❌ Containers weren't restarted (go back to Step 4b)
  • ❌ Old images cached (docker ps should show "Up X minutes", not hours)

Step 6: Verify Your Code Change (Optional)

If you added a comment in Step 1, verify it's in the compiled code:

ssh root@23.235.204.208 "docker exec blueline-alpha-api cat /app/dist/modules/health/health.controller.js | grep -i 'DEPLOYMENT TEST'"

Note: Build version check (Step 5) is faster and more reliable!

🎉 Congratulations! You just deployed to production!


Common Deployment Scenarios

Now that you've done one deployment, here are common scenarios:

Scenario 1: Deploy Code-Only Change

When: You changed TypeScript/JavaScript files only (no package.json, no schema)

Steps:

  1. ./scripts/validate-deployment-env.sh (validate environment)
  2. pnpm type-check (ensure no type errors)
  3. git status (ensure clean, committed changes)
  4. Deploy command (above)
  5. Verify with smoke tests

Time: ~10 minutes (good cache)

Scenario 2: Deploy with New Dependencies

When: You updated package.json (added/removed packages)

Steps:

  1. Same as Scenario 1, but...
  2. Build will be slower (~15-20 minutes)
  3. Cache will miss on pnpm install layer
  4. This is expected - don't worry!

Tip: Run ./scripts/analyze-build-cache.sh after to see cache impact

Scenario 3: Deploy Database Schema Change

When: You modified prisma/schema.prisma

Steps:

  1. Before deploy: Create migration locally

    pnpm db:migrate:dev --name descriptive_name
    
  2. Commit migration to git (critical!)

  3. Deploy normally (migrations run automatically on container startup)

  4. Verify migrations applied:

    ssh root@23.235.204.208 'docker logs blueline-alpha-api --tail 50 | grep -i migration'
    
  5. If seeds needed:

    ssh root@23.235.204.208 'docker exec blueline-alpha-api pnpm db:seed:prod'
    

Critical: Migrations run automatically. Seeds only if you changed seed files.

Scenario 4: Something Went Wrong (Rollback)

When: Deployment succeeded but app is broken

Steps:

  1. Don't panic! We can rollback in <5 minutes

  2. List available versions:

    ./scripts/rollback-deployment.sh root@23.235.204.208
    
  3. Select previous version (or type "previous"):

    ./scripts/rollback-deployment.sh root@23.235.204.208 previous
    
  4. Verify rollback worked:

    curl https://alpha.theblueline.com/health
    
  5. Investigate what went wrong (check logs, test locally)

Database safe: Rollback does NOT revert database changes (data is preserved)


Hands-On Exercises

Exercise 1: Read-Only Exploration

Goal: Get familiar with the system without deploying

# 1. View current deployment version
ssh root@23.235.204.208 'docker images | grep blueline-alpha'

# 2. Check container status
ssh root@23.235.204.208 'docker ps --filter "name=blueline-alpha"'

# 3. View recent logs
ssh root@23.235.204.208 'docker logs blueline-alpha-api --tail 20'

# 4. Test health endpoint
curl https://alpha.theblueline.com/health | jq

# 5. Check build cache history
./scripts/analyze-build-cache.sh

Exercise 2: Dry-Run Practice

Goal: Practice using dry-run mode before real deployments

# 1. Make a trivial change (add a comment somewhere)

# 2. Run dry-run
./scripts/docker-audit/build-cross-platform.sh --all --amd64 \
  --api-url https://alpha.theblueline.com/api \
  --push root@23.235.204.208 \
  --dry-run

# 3. Read the output carefully
#    - What version tag would be created?
#    - What's the estimated transfer size?
#    - What deployment steps would run?

# 4. Revert your change (git checkout or undo)

Exercise 3: Cache Performance Analysis

Goal: Understand how cache affects build time

# 1. Build locally (should be fast with cache)
./scripts/docker-audit/build-cross-platform.sh --api --local

# 2. Check cache performance
./scripts/analyze-build-cache.sh --detailed

# 3. Make a code-only change (add comment to any file)

# 4. Build again
./scripts/docker-audit/build-cross-platform.sh --api --local

# 5. Compare cache performance (should be similar or better)
./scripts/analyze-build-cache.sh --detailed

# Questions to answer:
# - What was the cache hit rate?
# - How much time was saved?
# - What layers were rebuilt?

Troubleshooting Your First Deployment

Problem: "Environment validation failed"

Symptom: ./scripts/validate-deployment-env.sh shows errors

Solution:

  1. Check which variables are missing (read error output)
  2. Copy .env.blueline-alpha.example to .env.blueline-alpha (if it doesn't exist)
  3. Ask team for production values (don't guess!)
  4. Re-run validation

Problem: "Type check failed"

Symptom: pnpm type-check shows TypeScript errors

Solution:

  1. Read error messages carefully
  2. Fix your code changes
  3. OR pull latest from main (if errors aren't from you)
  4. Re-run type-check

Problem: "Build fails during pnpm install"

Symptom: Docker build fails with npm/pnpm error

Solution:

  1. Check if pnpm-lock.yaml is committed to git
  2. Try: pnpm install locally (does it work?)
  3. If local works but Docker fails: Rebuild without cache
    docker builder prune -a
    ./scripts/docker-audit/build-cross-platform.sh --api --local
    

Problem: "Container smoke tests fail"

Symptom: Build succeeds but container won't start

Solution:

  1. Check logs: docker logs <container-name>
  2. Common causes:
    • Missing environment variable
    • Database connection failed
    • Port already in use
  3. See Deployment Troubleshooting for detailed guide

Problem: "Transfer to VPS times out"

Symptom: SSH transfer hangs or fails

Solution:

  1. Check VPS is reachable: ssh root@23.235.204.208 'echo ok'
  2. Check VPS disk space: ssh root@23.235.204.208 'df -h'
  3. If disk full: Clean old images
    ssh root@23.235.204.208 'docker system prune -a -f'
    

Best Practices (Learn These!)

1. Always Validate Before Deploy

DO:

./scripts/validate-deployment-env.sh  # Check env vars
pnpm type-check                       # Check types
git status                            # Check working directory clean

DON'T:

  • Skip validation (causes 20% of failures)
  • Deploy with uncommitted changes
  • Deploy without testing locally first

2. Use Dry-Run for Risky Changes

DO:

# Before deploying major changes:
./scripts/docker-audit/build-cross-platform.sh ... --dry-run
# Review output, then deploy for real

DON'T:

  • Skip dry-run for database migrations
  • Skip dry-run for dependency updates
  • Skip dry-run if you're uncertain

3. Monitor Build Cache Performance

DO:

# After each deploy, check cache:
./scripts/analyze-build-cache.sh

# If cache <70%, investigate why

DON'T:

  • Ignore slow builds (they indicate problems)
  • Prune cache unless necessary
  • Change Dockerfile without understanding cache impact

4. Keep Version History

DO:

  • Let system tag images automatically
  • Keep last 10 versions on VPS
  • Use version tags for rollback

DON'T:

  • Manually delete images (unless disk full)
  • Use :latest tag for rollback (not specific enough)

5. Document Your Deployments

DO: After each deployment, note:

  • Date/time
  • Version tag
  • What changed
  • Any issues encountered

DON'T:

  • Deploy without team communication
  • Deploy during peak hours (unless urgent)
  • Deploy on Friday afternoons (risky!)

Deployment Checklist (Print This!)

Pre-Deployment

  • [ ] Changes committed to git
  • [ ] Working directory clean (git status)
  • [ ] Environment validated (./scripts/validate-deployment-env.sh)
  • [ ] Types checked (pnpm type-check)
  • [ ] Tests passing (pnpm test)
  • [ ] Dry-run reviewed (if risky change)

During Deployment

  • [ ] Watch build output for errors
  • [ ] Note version tag created
  • [ ] Verify container smoke tests pass
  • [ ] Verify deployment smoke tests pass

Post-Deployment

  • [ ] Health check returns 200 (curl https://alpha.theblueline.com/health)
  • [ ] Web loads (curl https://alpha.theblueline.com)
  • [ ] Logs look normal (docker logs blueline-alpha-api --tail 50)
  • [ ] Cache performance acceptable (./scripts/analyze-build-cache.sh)
  • [ ] Document deployment (version, changes, issues)

If Problems

  • [ ] Check logs first (docker logs ...)
  • [ ] Try rollback if critical (./scripts/rollback-deployment.sh)
  • [ ] Ask team for help (don't struggle alone)
  • [ ] Document issue for future reference

Next Steps

Now that you've completed your first deployment:

  1. Read the full guides:

  2. Practice on staging:

    • Ask team about staging environment
    • Deploy test changes there first
    • Get comfortable with the workflow
  3. Learn the advanced features:

    • Rollback to specific versions
    • Cache analytics and optimization
    • Database migration workflows
  4. Join deployment reviews:

    • Shadow experienced team members
    • Ask questions during their deployments
    • Learn from their techniques

Getting Help

Stuck? Here's how to get help:

  1. Check documentation first:

    • Search help center for your error message
    • Read troubleshooting guide
    • Check this quick start guide
  2. Check logs:

    • Build logs (in terminal)
    • Container logs (docker logs ...)
    • Application logs (in admin UI)
  3. Ask the team:

    • Post in #deployments channel
    • Include: What you tried, error message, version tag
    • Share logs if relevant
  4. Emergency (production down):

    • Rollback immediately (./scripts/rollback-deployment.sh)
    • Then investigate root cause
    • Document for post-mortem

Quick Reference

Most Common Commands

# Validate before deploy
./scripts/validate-deployment-env.sh

# Type check
pnpm type-check

# Dry-run (preview)
./scripts/docker-audit/build-cross-platform.sh --all --amd64 \
  --api-url https://alpha.theblueline.com/api \
  --push root@23.235.204.208 \
  --dry-run

# Deploy for real
./scripts/docker-audit/build-cross-platform.sh --all --amd64 \
  --api-url https://alpha.theblueline.com/api \
  --push root@23.235.204.208 \
  --smoke-tests

# Rollback
./scripts/rollback-deployment.sh root@23.235.204.208 previous

# Check cache
./scripts/analyze-build-cache.sh

# View logs
ssh root@23.235.204.208 'docker logs blueline-alpha-api --tail 50'

# Health check
curl https://alpha.theblueline.com/health

Key Files

  • Environment: .env.blueline-alpha
  • Build script: scripts/docker-audit/build-cross-platform.sh
  • Validation: scripts/validate-deployment-env.sh
  • Rollback: scripts/rollback-deployment.sh
  • Cache analytics: scripts/analyze-build-cache.sh

VPS Details

  • Host: root@23.235.204.208
  • Path: /opt/sampo-alpha
  • API Port: 3003 (internal), 443 (public HTTPS)
  • Web Port: 3006 (internal), 443 (public HTTPS)
  • Database Port: 5436 (internal only)

Related Articles

Next Steps After This Tutorial

Advanced Topics

  • 📄 Deployment runbook: docs/operations/deployment-runbook.md
  • 📊 Implementation history: docs/operations/week2-week3-implementation-summary.md
  • 🔍 Quick reference: docs/operations/docker-deployment-quick-reference.md

Feedback? Found this guide helpful or confusing? Let the DevOps team know how we can improve it!

Was this article helpful?

Your feedback helps us improve our support content.

Still need assistance?

Our support team is ready to help you with more complex issues.

Contact Support