condui-server
August 12, 2026 · View on GitHub
Backend de sincronización para Condui. Provee autenticación, almacenamiento cifrado de conexiones y compartición entre usuarios.
- E2E encryption — el servidor nunca ve credenciales en texto plano
- Postgres como base de datos (via
docker compose, incluye el servicio bundled) - Tiers free / pro configurables sin redesplegar
- TLS automático vía Caddy + Let's Encrypt
Requisitos
| Herramienta | Versión mínima |
|---|---|
| Go | 1.25 |
| PostgreSQL | 14+ (o el servicio db bundled en docker compose) |
| Docker + Docker Compose | 24+ (solo para el despliegue) |
| Dominio con DNS apuntando al servidor | — |
Configuración
Copia el archivo de ejemplo y edita los valores:
cp .env.example .env
| Variable | Default | Descripción |
|---|---|---|
JWT_SECRET | (requerido) | Clave secreta para firmar JWT. Genera una segura con openssl rand -hex 32 |
PORT | 8080 | Puerto HTTP interno |
DATABASE_URL | postgres://condui:condui@localhost:5432/condui?sslmode=disable | DSN de conexión a Postgres |
POSTGRES_PASSWORD | condui | Contraseña del servicio Postgres embebido en docker-compose.yml/.prod.yml |
JWT_EXPIRY_MINUTES | 15 | Duración del access token |
REFRESH_EXPIRY_DAYS | 30 | Duración del refresh token |
ALLOWED_ORIGINS | * | Orígenes CORS permitidos (en prod: https://tu-dominio.com) |
JWT_SECRET es obligatorio en producción. El valor por defecto del ejemplo no es seguro.
Despliegue con Docker (recomendado)
1. Configura el dominio en Caddyfile
# Caddyfile
tu-dominio.com {
reverse_proxy server:8080
encode gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options nosniff
X-Frame-Options DENY
-Server
}
}
2. Crea el .env
JWT_SECRET=$(openssl rand -hex 32)
echo "JWT_SECRET=$JWT_SECRET" > .env
echo "ALLOWED_ORIGINS=https://tu-dominio.com" >> .env
3. (Solo si vienes de una versión anterior con SQLite) Migra los datos
Si ya tenías un despliegue corriendo con el condui.db de SQLite, migra sus datos a Postgres antes de arrancar el servidor:
# Levanta solo Postgres primero
docker compose up -d db
# Copia los datos del SQLite viejo (ajusta la ruta si es distinta)
DATABASE_URL=postgres://condui:${POSTGRES_PASSWORD:-condui}@localhost:5432/condui?sslmode=disable \
go run ./cmd/migrate-sqlite -sqlite ./data/condui.db
Es seguro re-ejecutarlo: usa ON CONFLICT DO NOTHING, así que correrlo dos veces no duplica nada. Instalaciones nuevas (sin SQLite previo) se saltan este paso — Postgres arranca con las tablas vacías y tier_limits sembrado por defecto.
4. Levanta los servicios
docker compose up -d
Caddy obtiene el certificado TLS automáticamente en el primer arranque.
Comandos útiles
# Ver logs en tiempo real
docker compose logs -f server
# Reiniciar el servidor
docker compose restart server
# Actualizar a la última imagen
docker compose pull && docker compose up -d
# Detener todo
docker compose down
# Detener y borrar datos (¡irreversible!)
docker compose down -v
Ejecución local (desarrollo)
# Levantar solo Postgres (expuesto en localhost:5432)
docker compose up -d db
# Instalar dependencias
go mod download
# Ejecutar con variables de entorno del .env
export $(cat .env | xargs)
go run .
El servidor queda disponible en http://localhost:8080.
API
Base URL: https://tu-dominio.com/api/v1
Autenticación
| Método | Ruta | Descripción |
|---|---|---|
POST | /auth/register | Crear cuenta |
POST | /auth/login | Iniciar sesión → access + refresh token |
POST | /auth/refresh | Renovar access token |
POST | /auth/logout | Cerrar sesión (invalida refresh token) |
GET | /auth/me | Datos del usuario autenticado |
PUT | /auth/identity | Subir clave pública X25519 |
Las rutas autenticadas requieren el header:
Authorization: Bearer <access_token>
Sincronización de blobs
| Método | Ruta | Descripción |
|---|---|---|
GET | /blobs | Listar blobs del usuario |
GET | /blobs/:id | Descargar blob cifrado |
POST | /blobs | Crear blob |
PUT | /blobs/:id | Actualizar blob |
DELETE | /blobs/:id | Eliminar blob |
Compartición (plan pro)
| Método | Ruta | Descripción |
|---|---|---|
POST | /shares | Crear invitación de compartición |
GET | /shares/sent | Ver invitaciones enviadas |
GET | /shares/received | Ver invitaciones recibidas |
PUT | /shares/:id/accept | Aceptar invitación |
DELETE | /shares/:id | Revocar / rechazar |
Tiers
Los límites se almacenan en la tabla tier_limits y se pueden cambiar sin redesplegar:
# Ajustar límite de blobs para el plan free
docker compose exec db psql -U condui -d condui \
-c "UPDATE tier_limits SET max_count = 20 WHERE tier='free' AND resource='blobs';"
| Tier | Blobs | Dispositivos | Compartición |
|---|---|---|---|
free | 10 | 2 | No |
pro | Ilimitado | Ilimitado | Sí |
Migración desde SQLite
Herramienta de un solo uso para copiar los datos de un condui.db (SQLite, versiones anteriores del servidor) a Postgres. Corre las migraciones de Postgres automáticamente antes de copiar, así que no hace falta haber arrancado el servidor primero.
go run ./cmd/migrate-sqlite -sqlite ./data/condui.db -postgres "$DATABASE_URL"
Flags:
-sqlite ruta al archivo SQLite de origen (default: $SQLITE_PATH o ./data/condui.db)
-postgres DSN de Postgres destino (default: $DATABASE_URL o postgres://condui:condui@localhost:5432/condui?sslmode=disable)
Migra users, refresh_tokens, blobs, share_invites y tier_limits (este último sobrescribe los valores sembrados por defecto, por si habías personalizado algún límite a mano). Es idempotente — usa ON CONFLICT DO NOTHING para todo salvo tier_limits — así que puedes volver a correrla sin duplicar datos si algo falla a mitad de camino.
Gestión de usuarios
Herramienta CLI incluida para administración directa de la base de datos.
Ejecutar desde condui-server/
# Listar todos los usuarios
go run ./cmd/manage list
# Crear cuenta
go run ./cmd/manage create admin@tudominio.com ContraseñaSegura1
# Activar plan pro con fecha de caducidad
go run ./cmd/manage set-tier user@tudominio.com pro 2026-12-31
# Revertir a free (sin fecha = inmediato, sin caducidad futura)
go run ./cmd/manage set-tier user@tudominio.com free
# Cambiar contraseña
go run ./cmd/manage reset-password user@tudominio.com NuevaPass456
# Con base de datos en un DSN personalizado
go run ./cmd/manage -db postgres://condui:condui@localhost:5432/condui?sslmode=disable list
Ejecutar contra el servidor en producción (Docker)
# Copiar el binario al contenedor del servidor y ejecutar ahí, apuntando al
# servicio "db" por su nombre en la red interna de docker-compose
docker compose exec server sh -c "
cd /app && go run ./cmd/manage -db postgres://condui:\$POSTGRES_PASSWORD@db:5432/condui?sslmode=disable list
"
Nota sobre caducidad: cuando el
tier_expires_atvence, el tier efectivo pasa afreeautomáticamente en el próximo login o renovación de token. No es necesario ningún cron job ni intervención manual.
Flags del CLI
-db string DSN de Postgres (default: $DATABASE_URL o postgres://condui:condui@localhost:5432/condui?sslmode=disable)
Backup
# Dump completo (dentro del contenedor de postgres)
docker compose exec db pg_dump -U condui -d condui -F c -f /tmp/condui.dump
docker compose cp db:/tmp/condui.dump ./backup-$(date +%Y%m%d).dump
# Restaurar
docker compose cp ./backup-20260101.dump db:/tmp/condui.dump
docker compose exec db pg_restore -U condui -d condui --clean /tmp/condui.dump
Para automatizarlo, añade una tarea cron en el servidor:
# /etc/cron.daily/condui-backup
#!/bin/bash
docker compose -f /path/to/docker-compose.prod.yml exec -T db \
pg_dump -U condui -d condui -F c > /backups/condui-$(date +%Y%m%d).dump
Variables de entorno — referencia completa
# .env
JWT_SECRET=<openssl rand -hex 32>
PORT=8080
DATABASE_URL=postgres://condui:condui@localhost:5432/condui?sslmode=disable
POSTGRES_PASSWORD=condui
JWT_EXPIRY_MINUTES=15
REFRESH_EXPIRY_DAYS=30
ALLOWED_ORIGINS=https://sync.condui.app