4f695d7e62
The create_instance endpoint was expecting tool_type_id and display_name as query parameters, but the frontend sends them in the JSON body. Added CreateInstanceRequest Pydantic model to properly parse the request body. Fixes 422 Unprocessable Content error on instance creation.
Headquarter API
The backend API for Headquarter - a self-hosted platform for managing projects, git repositories, and development tools.
Overview
Built with FastAPI and SQLAlchemy (async), using PostgreSQL for data storage and Docker for tool instance management.
Tech Stack
- Framework: FastAPI (Python 3.12+)
- Database: PostgreSQL 15+ with asyncpg
- ORM: SQLAlchemy 2.0 (async)
- Auth: OAuth2 via Authentik with session cookies
- Migrations: Alembic
- Tools: Docker Compose for instance management
Quick Start
Prerequisites
- Python 3.12+
- PostgreSQL 15+ running locally
- Docker (for tool instances)
Setup
cd apps/api
# Create virtual environment
python -m venv .venv
source .venv/bin/activate
# Install dependencies
pip install -e ".[dev]"
# Set up database
# Ensure PostgreSQL is running with a 'headquarter' database
# Run migrations
alembic upgrade head
# Start development server
uvicorn src.main:app --reload --port 8000
The API will be available at http://localhost:8000.
Interactive Documentation
Once running, visit:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- OpenAPI JSON: http://localhost:8000/openapi.json
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | - | PostgreSQL connection string |
API_BASE_URL |
Yes | - | Public API URL (e.g., https://api.example.com) |
AUTHENTIK_DOMAIN |
Yes | - | Authentik server domain |
AUTHENTIK_CLIENT_ID |
Yes | - | OAuth2 client ID |
AUTHENTIK_CLIENT_SECRET |
Yes | - | OAuth2 client secret |
AUTHENTIK_APPLICATION_SLUG |
Yes | - | Authentik application slug |
WEB_BASE_URL |
Yes | - | Public frontend URL |
SESSION_SECRET |
Yes | - | Secret for session cookie signing |
COOKIE_DOMAIN |
No | - | Cookie domain (e.g., .example.com) |
UPLOAD_DIR |
No | ./uploads |
Directory for file uploads |
REPO_BASE_PATH |
No | ./repositories |
Base path for git repositories |
INSTANCES_BASE_PATH |
No | ./instances |
Base path for tool instances |
LOG_LEVEL |
No | INFO |
Logging level |
Development
Running Tests
# Run all tests
pytest
# Run specific test category
pytest -m unit # Unit tests (no DB)
pytest -m integration # Integration tests (requires DB)
# Run with coverage
pytest --cov=src --cov-report=html
Code Quality
# Format code
ruff format src tests
# Lint
ruff check src tests
# Type check
mypy src
Database Migrations
# Create new migration
alembic revision --autogenerate -m "description"
# Apply migrations
alembic upgrade head
# Rollback one migration
alembic downgrade -1
# Show current revision
alembic current
Architecture
Directory Structure
src/
├── api/ # API endpoint routers
│ ├── auth.py # OAuth2 authentication
│ ├── dashboard.py # Dashboard summary
│ ├── git_repositories.py # Git repo management
│ ├── health.py # Health checks
│ ├── projects.py # Project CRUD
│ ├── ssh_keys.py # SSH key management
│ ├── terminal.py # WebSocket terminal
│ ├── tool_instances.py # Tool instance management
│ ├── tool_types.py # Tool type definitions
│ ├── user_config.py # User preferences
│ └── users.py # User profile
├── auth/ # Authentication logic
│ ├── cookies.py # Cookie utilities
│ ├── dependencies.py # Auth dependencies
│ ├── oidc.py # OpenID Connect
│ └── session.py # Session management
├── config.py # Application settings
├── database.py # Database setup
├── main.py # FastAPI application
├── models/ # SQLAlchemy models
├── schemas/ # Pydantic schemas
├── services/ # Business logic
│ ├── docker.py # Docker Compose management
│ ├── terminal_manager.py # Terminal sessions
│ └── terminal_session.py # Terminal I/O
└── utils/ # Utilities
├── git_control.py # Git operations
├── git_files.py # File operations
├── git_history.py # History extraction
└── git_url_parser.py # URL parsing
Authentication Flow
- User clicks "Login" → redirects to Authentik OAuth
- Authentik redirects back with authorization code
- API exchanges code for tokens and fetches user info
- API creates session cookie (HMAC-signed, httpOnly)
- Frontend stores nothing - cookie sent automatically
- Subsequent requests include cookie for authentication
Data Flow
Client → FastAPI Router → Auth Dependency → Service Layer → Database
↓
Pydantic Models (validation)
↓
SQLAlchemy Models (ORM)
↓
PostgreSQL (storage)
API Endpoints
Authentication
GET /auth/login- Initiate OAuth loginGET /auth/callback- OAuth callbackGET /auth/me- Get current userPOST /auth/logout- Logout
Projects
GET /projects- List projectsPOST /projects- Create projectGET /projects/{id}- Get projectPUT /projects/{id}- Update projectDELETE /projects/{id}- Delete project
Git Repositories
GET /projects/{id}/repositories- List repositoriesPOST /projects/{id}/repositories- Create repositoryGET /projects/{id}/repositories/{id}- Get repositoryDELETE /projects/{id}/repositories/{id}- Delete repositoryGET /projects/{id}/repositories/{id}/files- List filesGET /projects/{id}/repositories/{id}/files/content- Get file contentPOST /projects/{id}/repositories/{id}/files/content- Update fileGET /projects/{id}/repositories/{id}/branches- List branchesGET /projects/{id}/repositories/{id}/history- Commit historyGET /projects/{id}/repositories/{id}/commits/{hash}- Commit detail
Tool Types
GET /tool-types- List tool typesPOST /tool-types- Create tool typeGET /tool-types/{id}- Get tool typePUT /tool-types/{id}- Update tool typeDELETE /tool-types/{id}- Delete tool type
Tool Instances
GET /tool-instances- List instancesPOST /tool-instances- Create instanceGET /tool-instances/{id}- Get instancePOST /tool-instances/{id}/start- Start instancePOST /tool-instances/{id}/stop- Stop instancePOST /tool-instances/{id}/restart- Restart instanceDELETE /tool-instances/{id}- Delete instanceGET /tool-instances/{id}/logs- Get logs
Terminal
WS /ws/tool-instances/{id}/terminal- WebSocket terminal
Users
GET /users/me- Get profilePUT /users/me- Update profilePOST /users/me/avatar- Upload avatarGET /users/me/config- Get configPATCH /users/me/config- Update config
SSH Keys
GET /ssh-keys- List keysPOST /ssh-keys- Create keyDELETE /ssh-keys/{id}- Delete key
Health
GET /health- System healthGET /health/db- Database health
Deployment
See the deployment documentation for Docker and Traefik setup.
Contributing
- Follow PEP 8 style guide
- Add tests for new endpoints
- Update documentation
- Run quality gates before committing