Neda/Back
2026-03-30 11:37:21 +03:30
..
alembic feat: refactor groups 2026-03-28 20:49:16 +03:30
core feat: add logger.py and add root to livekit.yaml 2026-03-29 20:24:16 +03:30
db feat: add pg_backup and refactor codes for livekit and websocket 2026-03-22 14:28:13 +03:30
domains fix(stable): fix secret 2026-03-30 11:37:21 +03:30
integrations/livekit fix: change livkit udp ports and add ttl for livekit token 2026-03-29 16:35:10 +03:30
scripts fix(stable): fix secret 2026-03-30 11:37:21 +03:30
tests fix: change livkit udp ports and add ttl for livekit token 2026-03-29 16:35:10 +03:30
.dockerignore intial project 2026-03-06 15:16:41 +03:30
.gitignore intial project 2026-03-06 15:16:41 +03:30
.python-version intial project 2026-03-06 15:16:41 +03:30
alembic.ini update project 2026-03-06 20:01:04 +03:30
docker-compose.yml fix(stable): fix secret 2026-03-30 11:37:21 +03:30
Dockerfile intial project 2026-03-06 15:16:41 +03:30
livekit.yaml fix(stable): fix secret 2026-03-30 11:37:21 +03:30
main.py feat: add middleware 2026-03-29 16:40:30 +03:30
pyproject.toml intial project 2026-03-06 15:16:41 +03:30
README.md feat: change livekit config in docker-compose.yml 2026-03-11 17:28:51 +03:30
requirements.txt feat: change livekit config in docker-compose.yml 2026-03-11 17:28:51 +03:30

NEDA Backend

NEDA is a FastAPI backend for real-time group voice communication. It includes authentication, user/group management, WebSocket signaling, Redis for real-time state, and PostgreSQL for persistent data.

Tech Stack

  • FastAPI + Uvicorn
  • SQLAlchemy (Async) + asyncpg
  • PostgreSQL
  • Redis
  • Alembic
  • LiveKit

Project Structure

core/          config, security, deps
alembic/       database migrations
db/            database/redis setup
domains/       domain modules (auth, users, admin, groups, realtime, notifications)
integrations/  external integrations (LiveKit)
scripts/       utility scripts (create_admin)
main.py        FastAPI app entrypoint

Active Routes

  • POST /auth/login
  • GET /users/
  • POST /admin/users
  • POST /admin/users/{user_id}/logout
  • POST /admin/users/{user_id}/reset-secret
  • GET /admin/users
  • GET /admin/groups
  • POST /groups/
  • GET /groups/my
  • GET /groups/admin/all
  • GET /groups/{group_id}/members
  • POST /groups/{group_id}/invite
  • DELETE /groups/{group_id}/members/{user_id}
  • WS /ws/groups/{group_id}

Environment Variables

Create a .env file in the project root:

APP_NAME=NEDA
DEBUG=False

SECRET_KEY=change-me
ACCESS_TOKEN_EXPIRE_MINUTES=30
ALGORITHM=HS256
SECRET_PASS_LENGTH=32

POSTGRES_DB=neda
POSTGRES_USER=neda_user
POSTGRES_PASSWORD=neda_pass
DATABASE_URL=postgresql+asyncpg://neda_user:neda_pass@postgres:5432/neda

REDIS_URL=redis://redis:6379/0

LIVEKIT_API_KEY=neda_key
LIVEKIT_API_SECRET=neda_secret
LIVEKIT_HOST=http://livekit:7880
LIVEKIT_PORT=7880
LIVEKIT_TCP_PORT=7881
LIVEKIT_UDP_PORT=7882

LiveKit note:

  • This project runs LiveKit v1.9.12 in Docker.
  • --api-key/--api-secret are not used; the server receives credentials via LIVEKIT_KEYS.
  • livekit.yaml is kept as a reference file and is not mounted/used at runtime in docker-compose.yml.
  • Docker-internal API host must be http://livekit:7880.
  • For local API execution (outside Docker), use a separate env value such as LIVEKIT_HOST=http://localhost:7780.

Run With Docker

docker compose up --build -d

Services:

  • API: http://localhost:8000
  • Swagger Docs: http://localhost:8000/docs
  • LiveKit: http://localhost:7780
  • Postgres: localhost:5432
  • Redis: localhost:6379

API logs:

docker compose logs -f api

Create Admin (Inside Docker)

After services are up, create the initial admin user inside the API container:

docker compose exec api python -m scripts.create_admin

The script asks for username and optional phone_number, creates the user with is_admin=True, and prints the initial secret.

Admin API Hardening

  • POST /admin/users creates only non-admin users.
  • Sending is_admin in the payload is not allowed and returns 422.
  • Admin creation is only allowed through the server-side script: scripts/create_admin.py.

Invalid payload example:

{
  "username": "new_user",
  "phone_number": "09123456789",
  "is_admin": true
}

Admin login:

  • Endpoint: POST /auth/login
  • Body:
{
  "username": "admin_username",
  "secret": "printed_secret"
}

Database Migrations (Alembic)

This project uses Alembic, and env.py reads DATABASE_URL from .env.

Apply migrations (inside Docker):

docker compose exec api alembic upgrade head

Create a new migration (autogenerate):

docker compose exec api alembic revision --autogenerate -m "your_message"

Check current DB revision:

docker compose exec api alembic current

Show migration history:

docker compose exec api alembic history

Important: run alembic upgrade head before starting the API in a new environment.

Local Development (Without Docker)

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Run migrations:

alembic upgrade head

Start API:

uvicorn main:app --reload

Realtime Notes

  • Presence is stored in Redis.
  • Speaker lock is managed atomically in Redis.
  • LiveKit tokens for listener/speaker roles are issued during the WebSocket flow.