soroban-abacus-flashcards/nas-deployment
Thomas Hallock 2082710ab2 fix: add retry middleware for zero-downtime deployments
The problem: During deployments, users pinned via sticky session to
the restarting container experienced ~60s of downtime because:
1. Health checks were too slow (10s interval)
2. No retry on failure - requests just failed

The fix:
- Add retry middleware: 3 attempts with 100ms initial interval
- Reduce health check interval from 10s to 3s
- Add health check timeout of 2s

Now when your pinned server restarts:
1. Request fails
2. Traefik retries on the OTHER healthy server
3. You get a response (maybe with new server_id cookie)

Combined with Redis for session state, this should give true
zero-downtime deployments.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 05:25:19 -06:00
..
ddns-data
.env.example
README.md
deploy.sh
docker-compose.blue.yaml fix: add retry middleware for zero-downtime deployments 2026-01-16 05:25:19 -06:00
docker-compose.green.yaml fix: add retry middleware for zero-downtime deployments 2026-01-16 05:25:19 -06:00
docker-compose.redis.yaml infra: add dedicated Redis compose file for compose-updater 2026-01-15 20:49:22 -06:00
docker-compose.yaml fix: add retry middleware for zero-downtime deployments 2026-01-16 05:25:19 -06:00
generate-compose.sh fix(deploy): remove depends_on from blue/green compose files 2026-01-15 11:39:32 -06:00

README.md

NAS Deployment for Soroban Abacus Flashcards

This directory contains the deployment configuration for running the Soroban Abacus Flashcards (apps/web) on your NAS at abaci.one.

Quick Deployment

After pushing code changes to trigger the GitHub Actions build:

# From the project root
./nas-deployment/deploy.sh

Manual Deployment

  1. Copy files to NAS:

    scp nas-deployment/docker-compose.yaml nas.home.network:/volume1/homes/antialias/projects/abaci.one/
    scp nas-deployment/.env nas.home.network:/volume1/homes/antialias/projects/abaci.one/
    
  2. Deploy:

    ssh nas.home.network "cd /volume1/homes/antialias/projects/abaci.one && docker-compose up -d"
    

Services

  • Soroban Flashcards: Main Next.js app at https://abaci.one
  • DDNS Updater: Keeps Porkbun DNS updated with current WAN IP
  • Watchtower: Auto-updates containers every 5 minutes when new images are pushed

Configuration

Environment Variables

Copy .env.example to .env and customize as needed.

DDNS Configuration

The Porkbun DDNS configuration is in ddns-data/ddns-config.json and handles:

  • Domain: abaci.one
  • Provider: Porkbun
  • Auto IP detection via ipinfo.io
  • TTL: 300 seconds

Traefik Integration

  • Automatic HTTPS via Let's Encrypt
  • HTTP → HTTPS redirect
  • HSTS headers for security

Monitoring

  • Container status: ssh nas.home.network 'cd /volume1/homes/antialias/projects/abaci.one && docker-compose ps'
  • Application logs: ssh nas.home.network 'cd /volume1/homes/antialias/projects/abaci.one && docker-compose logs -f soroban-abacus-flashcards'
  • DDNS web UI: http://[NAS-IP]:8000

Architecture

GitHub Actions → ghcr.io/antialias/soroban-abacus-flashcards:latest
                 ↓
NAS → docker-compose → Traefik → abaci.one
      ↓
      Watchtower (auto-update every 5min)
      DDNS (Porkbun IP sync)

Files

  • docker-compose.yaml: Main deployment configuration
  • deploy.sh: Automated deployment script
  • .env.example: Environment variables template
  • ddns-data/ddns-config.json: Porkbun DDNS configuration
  • README.md: This file