A modern RESTful API built with FastAPI for managing FreeRADIUS database operations. This API provides comprehensive endpoints for managing RADIUS users, NAS (Network Access Server) devices, accounting records, and group configurations.
- User Management: Complete CRUD operations for RADIUS users (radcheck table)
- NAS Management: Manage Network Access Server configurations
- Accounting Records: Query and monitor RADIUS accounting sessions (radacct)
- Group Management: Handle user groups, group checks, and group replies
- User Status Tracking: Real-time monitoring of online/offline user status
- Authentication: HTTP Basic Authentication for Swagger UI documentation
- Database Support: Compatible with MySQL, MariaDB, and PostgreSQL
- Auto-generated Documentation: Interactive Swagger UI and ReDoc
- CORS Enabled: Cross-Origin Resource Sharing support
- Python 3.8+
- MySQL/MariaDB or PostgreSQL database
- FreeRADIUS database schema
git clone <repository-url>
cd freeradius-apipython -m venv venv
source venv/bin/activate
# On Windows: venv\Scripts\activatepip install -r requirements.txtCopy the example environment file and configure it:
cp .env.example .envEdit .env file with your database credentials:
# Application Settings
APP_NAME=freeradius-api
APP_DEBUG=True
# Swagger/BASIC Auth Credentials
SWAGGER_USERNAME=admin
SWAGGER_PASSWORD=radius
# Database Settings
DB_TYPE=mariadb
DB_HOST=localhost
DB_PORT=3306
DB_NAME=radius
DB_USER=radius
DB_PASSWORD=radpasspython main.pyThe API will be available at http://localhost:8000
uvicorn main:app --host 0.0.0.0 --port 8000Once the application is running, access the interactive API documentation:
- Swagger UI:
http://localhost:8000/docs(requires authentication) - OpenAPI JSON:
http://localhost:8000/openapi.json(requires authentication)
Note: Documentation endpoints are protected with HTTP Basic Authentication using credentials from
.envfile.
GET /- Health check endpoint
GET /api/v1/users- Get all usersGET /api/v1/users/{username}- Get user by usernamePOST /api/v1/users- Create new userPUT /api/v1/users/{user_id}- Update userDELETE /api/v1/users/{user_id}- Delete user
GET /api/v1/nas/- Get all NAS devices (with optional filters)GET /api/v1/nas/{nas_id}- Get NAS by IDPOST /api/v1/nas/- Create new NASPUT /api/v1/nas/{nas_id}- Update NASDELETE /api/v1/nas/{nas_id}- Delete NAS
GET /api/v1/radacct/- Get accounting records (with filters)GET /api/v1/radacct/{radacctid}- Get specific accounting recordGET /api/v1/radacct/status/{username}- Get user online/offline status
GET /api/v1/radusergroup/- Get all user-group mappingsGET /api/v1/radusergroup/{id}- Get specific mappingPOST /api/v1/radusergroup/- Create user-group mappingPUT /api/v1/radusergroup/{id}- Update mappingDELETE /api/v1/radusergroup/{id}- Delete mapping
GET /api/v1/radgroupcheck/- Get all group check attributesGET /api/v1/radgroupcheck/{id}- Get specific group checkPOST /api/v1/radgroupcheck/- Create group checkPUT /api/v1/radgroupcheck/{id}- Update group checkDELETE /api/v1/radgroupcheck/{id}- Delete group check
GET /api/v1/radgroupreply/- Get all group reply attributesGET /api/v1/radgroupreply/{id}- Get specific group replyPOST /api/v1/radgroupreply/- Create group replyPUT /api/v1/radgroupreply/{id}- Update group replyDELETE /api/v1/radgroupreply/{id}- Delete group reply
GET /api/v1/radreply/- Get all user reply attributesGET /api/v1/radreply/{id}- Get specific replyPOST /api/v1/radreply/- Create replyPUT /api/v1/radreply/{id}- Update replyDELETE /api/v1/radreply/{id}- Delete reply
The API interacts with the following FreeRADIUS tables:
Stores user authentication credentials and check attributes.
| Column | Type | Description |
|---|---|---|
| id | Integer | Primary key |
| username | String(64) | RADIUS username |
| attribute | String(64) | Check attribute name |
| op | String(2) | Operator (e.g., :=, ==) |
| value | String(253) | Attribute value |
Network Access Server configurations.
| Column | Type | Description |
|---|---|---|
| id | Integer | Primary key |
| nasname | String(128) | NAS identifier/IP |
| shortname | String(32) | Short name |
| type | String(30) | NAS type |
| ports | Integer | Number of ports |
| secret | String(60) | RADIUS shared secret |
| server | String(64) | Server address |
| community | String(50) | SNMP community |
| description | String(200) | NAS description |
RADIUS accounting session records.
| Column | Type | Description |
|---|---|---|
| radacctid | Integer | Primary key |
| acctsessionid | String(64) | Session ID |
| username | String(64) | Username |
| nasipaddress | String(15) | NAS IP address |
| acctstarttime | DateTime | Session start time |
| acctstoptime | DateTime | Session stop time |
| acctsessiontime | Integer | Session duration (seconds) |
| acctinputoctets | Integer | Input bytes |
| acctoutputoctets | Integer | Output bytes |
| framedipaddress | String(15) | User IP address |
Maps users to groups.
| Column | Type | Description |
|---|---|---|
| id | Integer | Primary key |
| username | String(64) | Username |
| groupname | String(64) | Group name |
| priority | Integer | Priority (default: 1) |
Group-level check attributes.
| Column | Type | Description |
|---|---|---|
| id | Integer | Primary key |
| groupname | String(64) | Group name |
| attribute | String(64) | Check attribute |
| op | String(2) | Operator |
| value | String(253) | Attribute value |
Group-level reply attributes.
| Column | Type | Description |
|---|---|---|
| id | Integer | Primary key |
| groupname | String(64) | Group name |
| attribute | String(64) | Reply attribute |
| op | String(2) | Operator |
| value | String(253) | Attribute value |
curl -X POST "http://localhost:8000/api/v1/users" \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"attribute": "Cleartext-Password",
"op": ":=",
"value": "password123"
}'curl -X GET "http://localhost:8000/api/v1/radacct/status/testuser"curl -X POST "http://localhost:8000/api/v1/nas/" \
-H "Content-Type: application/json" \
-d '{
"nasname": "192.168.1.1",
"shortname": "router1",
"type": "cisco",
"ports": 1812,
"secret": "sharedsecret",
"description": "Main Router"
}'# Get all records
curl -X GET "http://localhost:8000/api/v1/radacct/"
# Filter by username
curl -X GET "http://localhost:8000/api/v1/radacct/?username=testuser"
# With pagination
curl -X GET "http://localhost:8000/api/v1/radacct/?skip=0&limit=50"freeradius-api/
βββ __init__.py
βββ main.py # Application entry point
βββ requirements.txt # Python dependencies
βββ .env.example # Environment variables template
βββ .gitignore # Git ignore rules
βββ src/
βββ api/
β βββ __init__.py
β βββ api.py # API utilities
β βββ endpoints/ # API route handlers
β β βββ __init__.py
β β βββ auth.py
β β βββ users.py
β β βββ nas.py
β β βββ radacct.py
β β βββ radusergroup.py
β β βββ radgroupcheck.py
β β βββ radgroupreply.py
β β βββ radreply.py
β βββ v1/
β βββ __init__.py
βββ core/
β βββ __init__.py
β βββ config.py # Configuration management
βββ db/
β βββ __init__.py
β βββ database.py # Database connection
βββ models/ # SQLAlchemy ORM models
β βββ __init__.py
β βββ user.py
β βββ operator.py
β βββ nas.py
β βββ radacct.py
β βββ radcheck.py
β βββ radgroupcheck.py
β βββ radgroupreply.py
β βββ radreply.py
β βββ radusergroup.py
βββ schemas/ # Pydantic schemas
β βββ __init__.py
β βββ auth.py
β βββ user.py
β βββ operator.py
β βββ nas.py
β βββ radacct.py
β βββ radcheck.py
β βββ radgroupcheck.py
β βββ radgroupreply.py
β βββ radreply.py
β βββ radusergroup.py
βββ services/ # Business logic layer
β βββ __init__.py
βββ utils/ # Utility functions
The application uses SQLAlchemy with optimized connection pooling:
- Pool Size: 200 connections
- Max Overflow: 100 additional connections
- Pool Timeout: 600 seconds
- Pool Recycle: 3600 seconds (1 hour)
- Pre-ping: Enabled for connection health checks
CORS is enabled for all origins by default. Modify in main.py for production:
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Change to specific domains in production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)- Swagger UI and OpenAPI documentation are protected with HTTP Basic Authentication
- Configure strong credentials in
.envfile - Use environment variables for sensitive data
- Never commit
.envfile to version control
Run tests using pytest:
# Run all tests
pytest
# Run with coverage
pytest --cov=src
# Run specific test file
pytest tests/unit/test_users.pyKey dependencies include:
- FastAPI: Modern web framework
- SQLAlchemy: ORM for database operations
- Pydantic: Data validation
- PyMySQL: MySQL/MariaDB driver
- psycopg2-binary: PostgreSQL driver
- python-dotenv: Environment variable management
- Uvicorn: ASGI server
- Alembic: Database migrations
See requirements.txt for complete list.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
If you encounter database connection errors:
- Verify database credentials in
.env - Ensure database server is running
- Check firewall rules
- Verify database exists and user has proper permissions
If you get import errors:
# Reinstall dependencies
pip install -r requirements.txt --force-reinstallIf port 8000 is already in use:
# Use a different port
uvicorn main:app --host 0.0.0.0 --port 8080For issues and questions:
- Open an issue on GitHub
- Check existing documentation
- Review FreeRADIUS documentation for database schema questions
Built with β€οΈ using FastAPI and FreeRADIUS