Compare commits

...
Author SHA1 Message Date
redshift f3c1658d69 fix: resolve docker compose dependency cycle and healthcheck issues 2026-02-24 05:40:31 +00:00
redshift 8870332980 feat: zero-downtime deployment with nginx and replicas
- Add nginx reverse proxy service with health checks
- Add 2 replicas for routstr service with healthchecks
- Modify auto_update.sh to use rolling updates (--build without down)
2026-02-23 07:56:30 +00:00
9qeklajcandGitHub 24f6519267 Merge pull request #372 from Routstr/fix-migration
quick fix for failed migration (first time setup)
2026-02-19 13:37:21 +01:00
9qeklajc f57beb6411 quick fix for failed migration 2026-02-19 13:27:09 +01:00
9qeklajcandGitHub 3e41e59a1d Merge pull request #371 from Routstr/add-reverted-changes
revert missing check
2026-02-19 12:54:28 +01:00
4 changed files with 98 additions and 7 deletions
+25
View File
@@ -1,4 +1,21 @@
services:
nginx:
image: nginx:latest
ports:
- 80:80
- 443:443
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
routstr:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost/v1/info"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
ui:
env_file:
- .env
@@ -15,6 +32,8 @@ services:
routstr:
build: .
deploy:
replicas: 2
depends_on:
- ui
volumes:
@@ -30,6 +49,12 @@ services:
- 8000:8000
extra_hosts: # Needed to access locally running models
- "host.docker.internal:host-gateway"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/v1/info')"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
tor:
image: ghcr.io/hundehausen/tor-hidden-service:latest
+26
View File
@@ -0,0 +1,26 @@
events {
worker_connections 1024;
}
http {
resolver 127.0.0.11 valid=10s;
server {
listen 80;
location / {
set $routstr_host "routstr";
proxy_pass http://$routstr_host:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /health {
set $routstr_host "routstr";
proxy_pass http://$routstr_host:8000/health;
access_log off;
}
}
}
+46 -2
View File
@@ -1,4 +1,6 @@
import os
import pathlib
import sqlite3
import time
from contextlib import asynccontextmanager
from typing import AsyncGenerator
@@ -181,11 +183,53 @@ async def create_session() -> AsyncGenerator[AsyncSession, None]:
yield session
def fix_cashu_migrations() -> None:
"""
Fixes Cashu wallet migrations that are not idempotent.
This specifically addresses the 'duplicate column name: public_keys' error
in the keysets table of Cashu's internal SQLite databases.
"""
project_root = pathlib.Path(__file__).resolve().parents[2]
wallet_dir = project_root / ".wallet"
if not wallet_dir.exists() or not wallet_dir.is_dir():
return
logger.info("Checking Cashu wallet databases for migration idempotency")
for db_file in wallet_dir.glob("*.sqlite3"):
try:
conn = sqlite3.connect(db_file)
cursor = conn.cursor()
# Check if keysets table exists
cursor.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name='keysets'"
)
if not cursor.fetchone():
conn.close()
continue
# Check if public_keys column exists
cursor.execute("PRAGMA table_info(keysets)")
columns = [info[1] for info in cursor.fetchall()]
if "public_keys" not in columns:
logger.info(f"Adding missing public_keys column to {db_file.name}")
cursor.execute("ALTER TABLE keysets ADD COLUMN public_keys TEXT")
conn.commit()
conn.close()
except Exception as e:
logger.warning(f"Could not check/fix Cashu database {db_file}: {e}")
def run_migrations() -> None:
"""Run Alembic migrations programmatically."""
import pathlib
try:
# Run Cashu migration fix first
fix_cashu_migrations()
# Get the path to the alembic.ini file
project_root = pathlib.Path(__file__).resolve().parents[2]
alembic_ini_path = project_root / "alembic.ini"
+1 -5
View File
@@ -81,11 +81,7 @@ if [ "$LOCAL_HASH" != "$REMOTE_HASH" ]; then
if git pull origin $(git branch --show-current) 2>&1 | tee -a "$LOG_FILE"; then
log_message "Successfully pulled latest changes"
# Stop current containers
log_message "Stopping current containers..."
sudo $DOCKER_COMPOSE_CMD down 2>&1 | tee -a "$LOG_FILE"
# Build and start updated containers
# Build and start updated containers (rolling update - no downtime)
log_message "Building and starting updated containers..."
if sudo $DOCKER_COMPOSE_CMD up -d --build 2>&1 | tee -a "$LOG_FILE"; then
log_message "Successfully updated and restarted containers"