GHOSTS API¶
The GHOSTS API is the central command-and-control server for the GHOSTS framework. It manages clients, distributes timelines, records activity, stores NPC data, and exposes a REST API plus a SignalR WebSocket hub.
Stack Overview¶
The API stack runs as five Docker containers:
| Container | Image | Port | Purpose |
|---|---|---|---|
ghosts-api |
dustinupdyke/ghosts |
5000 | .NET 10 REST API + SignalR |
ghosts-frontend |
dustinupdyke/ghosts-frontend |
4200 | Angular 20 management UI |
ghosts-postgres |
postgres:16.8 |
5432 | PostgreSQL 16 database |
ghosts-n8n |
docker.n8n.io/n8nio/n8n |
5678 | n8n workflow automation |
ghosts-grafana |
grafana/grafana |
3000 | Activity dashboards |
Installation¶
Step 1 — Choose a Host¶
- Development / testing: your local machine
- Training exercises: a dedicated server, VM, or cloud instance
- Production: a container orchestration platform (AWS ECS, Kubernetes, Docker Swarm)
Minimum requirements:
- Docker and Docker Compose v2+
- 4 GB RAM (8 GB+ recommended)
- 20 GB disk space
- Ports 3000, 4200, 5000, 5432, and 5678 available
Step 2 — Deploy¶
mkdir ghosts && cd ghosts
curl -O https://raw.githubusercontent.com/cmu-sei/GHOSTS/master/src/Ghosts.Api/docker-compose.yml
docker compose up -d
Verify:
docker ps -a
All five containers should be in a running state. PostgreSQL needs ~15 seconds on first start; the API will retry the connection automatically.
Step 3 — Verify¶
| URL | Expected |
|---|---|
| http://localhost:5000 | API home page |
| http://localhost:5000/swagger | Swagger UI (API v9) |
| http://localhost:4200 | Angular management frontend |
| http://localhost:3000 | Grafana (default: admin/admin) |
| http://localhost:5678 | n8n workflow editor |
Configuration¶
Environment Variables¶
Set these in a .env file alongside docker-compose.yml or directly in your container environment:
| Variable | Default | Description |
|---|---|---|
N8N_API_URL |
http://host.docker.internal:5678/api/v1/workflows |
n8n REST API endpoint (used by the API to list and validate workflows) |
N8N_API_KEY |
replace-me |
n8n API key for authenticating workflow API calls |
WEB_API_URL |
http://host.docker.internal:5000/api |
GHOSTS API URL served to the frontend container |
WEB_N8N_API_URL |
http://host.docker.internal:5678 |
n8n base URL served to the frontend container |
appsettings.json (Advanced)¶
Key settings in Ghosts.Api/appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Host=ghosts-postgres;Port=5432;Database=ghosts;User Id=ghosts;Password=scotty@1;"
},
"ApplicationSettings": {
"OfflineAfterMinutes": 30,
"MatchMachinesBy": "name",
"AnimatorSettings": {
"Animations": {
"IsEnabled": true
}
}
},
"CorsPolicy": {
"Origins": ["http://localhost:4200"]
}
}
Override values for production via environment variables or a mounted appsettings.Production.json.
Managing the Stack¶
# Stop
docker compose down
# Update to latest images
docker compose pull && docker compose up -d
# Restart a specific service
docker compose restart ghosts-api
# Follow API logs
docker compose logs -f ghosts-api
Data Persistence¶
| Directory | Contents |
|---|---|
./_db |
PostgreSQL data (machines, NPCs, timelines, activities) |
./_g |
Grafana dashboards and configuration |
./n8n_data |
n8n workflows and credentials |
Reset the database (destroys all data):
docker compose down && rm -rf ./_db && docker compose up -d
API Reference¶
Interactive documentation is available at http://YOUR-API-HOST:5000/swagger when the API is running.
Client Endpoints¶
Used by deployed GHOSTS client agents:
| Method | Path | Purpose |
|---|---|---|
| POST | /api/clientid |
Machine self-registration |
| GET/POST | /api/clientupdates |
Fetch pending timeline updates |
| POST | /api/clientresults |
Submit activity results |
| POST | /api/clienttimeline |
Submit active timeline |
| POST | /api/clientsurvey |
Submit system survey data |
Management Endpoints¶
Used by the frontend and operators:
| Resource | Base Path |
|---|---|
| Machines | /api/machines |
| Machine Groups | /api/machinegroups |
| Timelines | /api/timelines |
| Machine Timelines | /api/machinetimelines |
| Machine Updates | /api/machineupdates |
| NPCs | /api/npcs |
| NPC Generation | /api/npcs/generate |
| Scenarios | /api/scenarios |
| Executions | /api/executions |
| Trackables | /api/trackables |
| Surveys | /api/surveys |
| Webhooks | /api/webhooks |
| Animation Jobs | /api/animations/jobs |
| n8n Workflows | /api/animations/workflows |
SignalR Hub¶
Clients connect to /clientHub (WebSocket). Hub methods:
| Method | Direction | Purpose |
|---|---|---|
SendId |
Client → Server | Machine identification on connect |
SendResults |
Client → Server | Timeline execution results |
SendSurvey |
Client → Server | System survey data |
SendHeartbeat |
Client → Server | Keep-alive |
ReceiveId |
Server → Client | Returns machine GUID after registration |
The frontend connects to /api/hubs/activities for real-time animation and workflow events.
Troubleshooting¶
API returns database error on startup¶
PostgreSQL takes ~15 seconds to initialize on first run. The API retries automatically — wait and refresh.
If it persists, check PostgreSQL logs:
docker compose logs ghosts-postgres
Cannot connect from a client to the API¶
- Confirm the API is reachable from the client machine:
curl http://YOUR-API-HOST:5000/api - Ensure port 5000 is open in the firewall on the API host.
- Check
config/application.json(orapplication.yaml) on the client has the correctApiRootUrl.
Grafana container keeps restarting¶
Check ownership of the _g directory:
sudo chown -R 472:472 ./_g
docker compose restart ghosts-grafana
Social graph page shows no data¶
This is expected on fresh installations. Social graphs are created when NPCs are generated and animations are run. See Animator documentation.
Next Steps¶
- Connect client machines
- Explore the Frontend for machine and timeline management
- Configure Grafana dashboards
- Learn about timeline configuration
- Generate NPCs with the Animator