b40eb3e88c
Backend: - Add cloudflare_tunnel.py service for creating/deleting tunnels via Cloudflare API - Add public_url and tunnel_id fields to ToolInstance model - Update start_instance to create Cloudflare tunnel after container starts - Update stop_instance to delete tunnel before stopping container - Update delete_instance to cleanup tunnel before deletion - Update restart_instance to recreate tunnel on restart - Create Alembic migration 0011 for tunnel fields - Add Cloudflare config settings (API token, zone ID, account ID, base domain) Infrastructure: - Add cloudflared service to docker-compose.traefik.yml - Mount shared cloudflared_config volume between API and cloudflared containers - Add Cloudflare env vars to API service Frontend: - Update instance Open button to handle both full URLs and proxy paths The instance URL is now set to the Cloudflare tunnel public URL when available, falling back to the API proxy path if tunnel creation fails.
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