FastAPI firmware file server with upload UI and syslog receiver
Project description
FWServe
A FastAPI-based firmware file server that automatically serves .bin files from a configured directory, with a web upload UI and integrated syslog receiver.
Features
- Automatic detection of new
.binfiles - RESTful API for listing and downloading files
- Web UI for uploading
.binfiles - Integrated syslog server (UDP + TCP)
- Real-time syslog viewer with filtering
- CLI for easy installation as a systemd service
- Runs as a Linux systemd service
Installation
From PyPI
pip install fwserve
From Source
# Clone the repository
git clone https://github.com/yourusername/fwserve.git
cd fwserve
# Install with pip
pip install .
# Or install with development dependencies
pip install -e ".[dev]"
Quick Start
Run in Development Mode
# Run with default settings (port 8080, current directory)
fwserve run
# Run with custom settings
fwserve run --port 8080 --directory /path/to/files --reload
Install as a Service (Linux)
# Install with default settings (requires root)
sudo fwserve install
# Install with custom settings
sudo fwserve install --port 80 --syslog-port 514
# Check service status
fwserve status
# Uninstall the service
sudo fwserve uninstall
API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check |
/files |
GET | List available .bin files |
/files/{filename} |
GET | Download a specific file |
/upload |
GET | Upload form UI |
/upload |
POST | Upload a .bin file |
/syslog |
GET | Real-time syslog viewer UI |
/syslog/history |
GET | Get recent syslog entries |
/syslog/stream |
GET | SSE stream of syslog entries |
CLI Commands
# Show help
fwserve --help
# Run the server
fwserve run --host 0.0.0.0 --port 8080 --directory ./files
# Install as systemd service (requires root)
sudo fwserve install --port 80 --syslog-port 514
# Check service status
fwserve status
# Uninstall service (requires root)
sudo fwserve uninstall
Configuration
Configuration is done via environment variables:
Server Settings
| Variable | Default | Description |
|---|---|---|
FWSERVE_HOST |
0.0.0.0 |
Host to bind to |
FWSERVE_PORT |
8080 |
HTTP port to listen on |
FWSERVE_DIRECTORY |
. |
Directory to serve files from |
FWSERVE_LOG_LEVEL |
INFO |
Logging level |
FWSERVE_TIMEZONE |
America/New_York |
Timezone for timestamps |
Upload Settings
| Variable | Default | Description |
|---|---|---|
FWSERVE_UPLOAD_MAX_BYTES |
104857600 |
Maximum upload size (100MB) |
Syslog Settings
| Variable | Default | Description |
|---|---|---|
SYSLOG_ENABLE_UDP |
true |
Enable UDP syslog listener |
SYSLOG_ENABLE_TCP |
true |
Enable TCP syslog listener |
SYSLOG_UDP_PORT |
5514 |
UDP port for syslog |
SYSLOG_TCP_PORT |
5514 |
TCP port for syslog |
SYSLOG_LOG_FILE |
<directory>/syslog.log |
Path to syslog storage file |
SYSLOG_TAIL_SIZE |
5000 |
Number of entries to keep in memory |
SYSLOG_HISTORY_LIMIT |
500 |
Max entries returned by history endpoint |
Usage Examples
List available files
curl http://localhost:8080/files
Response:
{
"files": ["firmware_v1.0.bin", "update_v2.1.bin"]
}
Download a file
curl -O http://localhost:8080/files/firmware_v1.0.bin
Upload a file
curl -X POST -F "file=@firmware.bin" http://localhost:8080/upload
Send syslog messages
# UDP
echo "<14>Test message from host1" | nc -u localhost 5514
# TCP
echo "<14>Test message from host1" | nc localhost 5514
Get syslog history with filters
# Get all entries
curl http://localhost:8080/syslog/history
# Filter by host
curl "http://localhost:8080/syslog/history?host=router1"
# Filter by severity and message
curl "http://localhost:8080/syslog/history?severity=err&q=failed"
Running Tests
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Run type checking
mypy src/fwserve/
# Run linter
ruff check src/
Building the Package
# Install build dependencies
pip install build
# Build wheel and sdist
python -m build
# The built packages will be in dist/
ls dist/
# fwserve-1.0.0-py3-none-any.whl
# fwserve-1.0.0.tar.gz
Service Management
After installing with fwserve install:
# Start service
sudo systemctl start fwserve
# Stop service
sudo systemctl stop fwserve
# Restart service
sudo systemctl restart fwserve
# View status
sudo systemctl status fwserve
# View logs
sudo journalctl -u fwserve -f
Security Notes
- Only
.binfiles are served/uploaded - Path traversal attacks are blocked
- Service runs as dedicated non-root user (
fwserve) - Systemd security hardening is enabled
- Files directory has restricted write access
Project Structure
fwserve/
├── pyproject.toml # Package configuration
├── README.md
├── src/
│ └── fwserve/
│ ├── __init__.py
│ ├── app.py # FastAPI application
│ ├── cli.py # Click CLI
│ ├── config.py # Configuration
│ ├── file_watcher.py # Directory monitoring
│ ├── syslog_parser.py # Syslog message parsing
│ ├── syslog_server.py # UDP/TCP listeners
│ └── syslog_store.py # File-backed storage
└── tests/
├── test_main.py
└── test_syslog.py
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fwserve-1.0.1.tar.gz.
File metadata
- Download URL: fwserve-1.0.1.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c2c09603e3f9508a1cae27c8a8ea0fd316fc27f3c416fa5ff8898a611a1c9df
|
|
| MD5 |
0ffd7157666e7238e2989d4eb5b42a50
|
|
| BLAKE2b-256 |
8223f2d5373e0d0eea4d6fa33ef3d148c33ea33b2bb1d3031091d77a76f92df3
|
Provenance
The following attestation bundles were made for fwserve-1.0.1.tar.gz:
Publisher:
ci.yml on liptonj/workflows2025
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fwserve-1.0.1.tar.gz -
Subject digest:
5c2c09603e3f9508a1cae27c8a8ea0fd316fc27f3c416fa5ff8898a611a1c9df - Sigstore transparency entry: 845013601
- Sigstore integration time:
-
Permalink:
liptonj/workflows2025@f2c246c9ac5200872905d4f1e5d1923f2af17e66 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/liptonj
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@f2c246c9ac5200872905d4f1e5d1923f2af17e66 -
Trigger Event:
push
-
Statement type:
File details
Details for the file fwserve-1.0.1-py3-none-any.whl.
File metadata
- Download URL: fwserve-1.0.1-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54a5ddb285a391940adf1154831988dc3a2b73d17be768311e20f768a6db815c
|
|
| MD5 |
44b83f47c6fb029ca9384757aacbcfd0
|
|
| BLAKE2b-256 |
e8a183f156d2c191b87f495722cc7cdc7908950ecb97a22f28ed5c2389c92008
|
Provenance
The following attestation bundles were made for fwserve-1.0.1-py3-none-any.whl:
Publisher:
ci.yml on liptonj/workflows2025
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fwserve-1.0.1-py3-none-any.whl -
Subject digest:
54a5ddb285a391940adf1154831988dc3a2b73d17be768311e20f768a6db815c - Sigstore transparency entry: 845013602
- Sigstore integration time:
-
Permalink:
liptonj/workflows2025@f2c246c9ac5200872905d4f1e5d1923f2af17e66 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/liptonj
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@f2c246c9ac5200872905d4f1e5d1923f2af17e66 -
Trigger Event:
push
-
Statement type: