Server Administration & Logistics Toolkit
S.A.L.T. is a self-hosted web dashboard and Discord bot for administering Nitrado-hosted DayZ servers on Xbox, PlayStation, and PC. It combines server operations, Discord automation, player services, mission-file tooling, analytics, and an optional AI-assisted configuration workflow in one multi-tenant application.
S.A.L.T. performs real provider and Discord actions. Start with dedicated test credentials and a non-production server whenever possible.
- Register and manage multiple Nitrado DayZ services per Discord guild
- View server status, player counts, uptime, settings, statistics, and activity
- Start, stop, and restart servers with role-based authorization
- Inspect and create scheduled Nitrado tasks
- Synchronize and parse
.ADM/.RPTlogs for online state, kills, player activity, feeds, and analytics - Access the administrative console, backups, log downloads, and support links
- Keep operations scoped to the exact guild and server selected by the operator
- Browse, validate, edit, and upload DayZ XML and JSON mission files
- Configure mission initialization and reusable composition content
- Build and activate scheduled configuration-rotation presets
- Review spawn exclusions and event-health information
- Find loot and visualize loot-despawn activity on operator-supplied maps
- Queue audited player teleports and enforce position-restriction rules
- Live server-status embeds and player/restart voice-channel counters
- Kill feeds, faction feeds, restart notifications, and moderation logs
- Slash commands for status, online players, statistics, leaderboards, linking, bans, whitelists, server control, and more
- Discord OAuth login with guild- and server-scoped owner, admin, moderator, and player access
- Player portal with linked identities, statistics, kill history, map/radar access, and economy information
- Wallets, bank accounts, transaction history, and supply auditing
- Shops, item provisioning, rentals, casino games, bounties, and leaderboards
- Factions, reports, account-link controls, and alt-account review
- Feature flags so operators can enable only the systems their community uses
- AI chat and analysis for supported DayZ configuration files
- OpenAI-compatible providers or the GitHub Copilot SDK
- Server-aware suggestions using authorized statistics and file context
- Optional GitHub repository links and pull-request workflows for reviewed changes
- User-owned GitHub Actions automation templates under
templates/dayz-server-automation/
Some features require an approved guild, an enabled server, a linked player identity, a feature flag, or a role with the appropriate capability. Provider support can also differ by DayZ platform and Nitrado service configuration.
Discord users ──► Discord bot ──────────────┐
│ │
Web users ─────► Express dashboard ├──► PostgreSQL
│ │
└──► Nitrado / GitHub ──┘
The backend and bot are separate Node.js processes. They coordinate through the same PostgreSQL database; they do not call each other over HTTP. The frontend is vanilla JavaScript and Tailwind CSS served by Express.
- Docker Engine with Docker Compose v2
- A Discord application and bot
- A Nitrado account with at least one DayZ service
- A Nitrado long-life API token for the account that owns those services
- A public HTTPS reverse proxy for production web deployments
- Node.js 22 (
>=22 <23) - npm
- PostgreSQL 15, or Docker for the supplied local stack
Optional integrations:
- A GitHub account/token for repository-backed suggestions and automation
- An OpenAI-compatible inference provider or GitHub Copilot for the built-in AI assistant
- Hermes Agent and optionally Ollama for AI-assisted development
git clone https://github.com/Kitty-Shackleford/SALT.git
cd SALT
cp .env.example .envKeep .env on the deployment host. Never commit it or paste its contents into an issue, pull request, chat, screenshot, or log.
In the Discord Developer Portal:
-
Create an application and bot.
-
Record the application/client ID, client secret, and bot token in
.env. -
Add an OAuth redirect URL for every configured public hostname. If the dashboard and player portal use different hostnames, register both:
https://your-dashboard.example/auth/discord/callback https://your-player-portal.example/auth/discord/callback -
Invite the bot with the
botandapplications.commandsscopes. Grant only the Discord permissions needed by the features you enable. Status-channel setup, feed setup, and voice-channel counters require permissions to manage the relevant channels, messages, and webhooks. -
Set
DISCORD_GUILD_IDduring initial setup if you want commands registered to one test guild immediately. Leave it empty for global registration, which can take longer to propagate.
At minimum, review and set:
NODE_ENV=production
DEPLOYMENT_MODE=full
APP_NAME=S.A.L.T.
DASHBOARD_URL=https://your-dashboard.example
PLAYER_PORTAL_URL=https://your-player-portal.example
SESSION_SECURE_COOKIE=true
RATE_LIMIT_ENABLED=true
DISCORD_CLIENT_ID=...
DISCORD_CLIENT_SECRET=...
DISCORD_BOT_TOKEN=...
DISCORD_GUILD_ID=...
DASHBOARD_OWNER_DISCORD_ID=...
SESSION_SECRET=...
ENCRYPTION_KEY=...
POSTGRES_PASSWORD=...Generate secrets locally on the deployment host:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"Use separate output values for SESSION_SECRET and ENCRYPTION_KEY. ENCRYPTION_KEY must be exactly 64 hexadecimal characters. DASHBOARD_OWNER_DISCORD_ID identifies the initial global owner. The bot path verifies that configured ID through live guild membership; the web path verifies the same ID through Discord OAuth. S.A.L.T. never silently replaces an existing different owner.
The supplied Compose file binds the dashboard to 127.0.0.1:3000. Put a trusted HTTPS reverse proxy in front of it; do not expose the backend port directly to the internet.
docker compose up -d --build backend botCompose starts PostgreSQL and runs the one-shot database initializer before the backend and bot become available.
Inspect startup state without printing environment values:
docker compose ps
docker compose logs --since=10m backend bot
curl -I http://127.0.0.1:3000/docker compose run --rm bot node deploy-commands.jsRun this again whenever command definitions change. Guild-scoped commands normally appear immediately; global commands may take up to an hour.
- Invite the bot to the Discord guild.
- As the guild owner or a Discord administrator, run
/register-tokenand provide the Nitrado token in the command's private interaction. - S.A.L.T. verifies the Nitrado account, discovers its DayZ services, encrypts the token, and leaves discovered servers disabled.
- Sign in at
DASHBOARD_URLthrough Discord OAuth. - Enable only the servers you intend to manage.
- Run
/setup-statusfor the status channels and/setup-feedsfor optional Discord feeds. - Configure server roles, account-link policy, feature flags, automation, and player-facing systems from the dashboard.
Use /server-status to confirm registration. Players can then use /link or the configured account-link workflow before accessing identity-scoped features.
For a deployment without the website:
DEPLOYMENT_MODE=botThen start the bot and its database dependencies:
docker compose up -d --build botThe web dashboard, Discord OAuth, and browser-only administration pages are unavailable in this mode.
Install both dependency boundaries and create an isolated local environment:
npm ci
npm ci --prefix bot
npm run local:setuplocal:setup creates an ignored, mode-0600 .env.local with generated local session, encryption, and database secrets. It never overwrites an existing file or prints generated values.
Add credentials for a dedicated Discord test application and test guild to .env.local, including this OAuth callback:
http://localhost:3000/auth/discord/callback
Start the isolated stack and register commands:
npm run local:up
npm run local:commandsOpen http://localhost:3000. Useful development commands:
npm run local:ps
npm run local:logs
npm run local:downLocal mode still makes real Discord, Nitrado, GitHub, and AI-provider calls when those credentials are supplied. Use test accounts and disposable services.
Hermes Agent is an optional coding assistant; it is not required to run S.A.L.T. The repository includes AGENTS.md, which gives Hermes the project architecture, security boundaries, commands, and conventions automatically when Hermes starts from the repository root.
Linux, macOS, or WSL2:
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
hermes setup
hermes doctorOn native Windows, use the official PowerShell installer documented in the Hermes installation guide.
Choose a model/provider with:
hermes modelThen work from the S.A.L.T. checkout:
cd SALT
hermesA good first request is:
Read AGENTS.md, inspect the relevant source and tests, make the smallest safe change, and run the affected tests and lint before reporting completion.
Recommended workflow:
- Start Hermes from the repository root so
AGENTS.mdis loaded. - Ask it to inspect definitions, usages, tests, and package manifests before editing.
- Keep production credentials out of prompts and test fixtures.
- Require focused tests, then
npm testandnpm run lintfor changes that can affect runtime behavior. - Review
git diffyourself before committing or publishing. - Use
hermes -wfor parallel coding sessions so each agent works in an isolated Git worktree.
Hermes documentation: installation, context files, and providers.
This setup keeps the coding-assistant model on your machine. Choose a tool-capable model that fits your hardware; larger coding models generally produce better multi-file changes but need substantially more RAM or VRAM.
Linux:
curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen3.5:27bFor macOS or Windows, use the installer from ollama.com/download. Replace the example model with another tool-capable model if the 27B model does not fit your hardware.
Hermes requires at least a 64K-token context window for reliable agent/tool use. For a manually started Ollama server:
OLLAMA_CONTEXT_LENGTH=64000 ollama serveFor a systemd-managed Ollama service on Linux, run sudo systemctl edit ollama.service, add the following override, then restart the service:
[Service]
Environment="OLLAMA_CONTEXT_LENGTH=64000"sudo systemctl daemon-reload
sudo systemctl restart ollamaAfter sending the model a request, verify the loaded model's CONTEXT value:
ollama psRun:
hermes modelChoose Custom endpoint (self-hosted / VLLM / etc.), then enter:
API base URL: http://localhost:11434/v1
API key: no-key (a non-secret placeholder; Ollama does not authenticate local requests)
Model: qwen3.5:27b
Context: 64000
Start a new session from the repository root:
cd SALT
hermesUse /model inside a running session to switch among providers already configured in Hermes. Use the terminal command hermes model to add or reconfigure a provider.
Local models are best used for bounded, low-risk work that is easy to validate. Keep security, authorization, migrations, money handling, provider mutations, deployment, and destructive operations under human review, and always run the repository's real checks after an AI-generated change.
The dashboard AI assistant and Hermes Agent are separate systems:
- Hermes + Ollama helps a developer work on this repository.
- S.A.L.T. AI Assistant helps an authorized operator analyze and propose changes to DayZ configuration files.
S.A.L.T.'s assistant can use an operator-supplied OpenAI-compatible endpoint. For a backend running directly on the same host as Ollama, the optional deployment-wide fallback can be configured in the private environment file:
AI_API_BASE_URL=http://127.0.0.1:11434/v1/
AI_API_KEY=local-ollama-placeholder
AI_MODEL=qwen3.5:27b
AI_API_TIMEOUT_MS=60000
AI_MAX_OUTPUT_TOKENS=16384The placeholder is not an Ollama secret; the current OpenAI-compatible client requires a non-empty bearer value. Never reuse a real credential as the placeholder.
When S.A.L.T. runs in Docker, 127.0.0.1 refers to the backend container, not the host. This repository does not bundle or expose an Ollama service. Configure a trusted endpoint reachable from the backend container, keep it off the public internet, and verify network isolation before enabling it. Per-user provider connections intentionally reject private/loopback destinations to prevent server-side request forgery, so local Ollama should be configured by the deployment operator rather than through the browser connection form.
See External integrations for provider security, GitHub linking, request limits, and AI file-replacement safeguards.
Before opening a pull request or deploying a change:
npm test
npm run lint
npm run security:audit
npm audit
npm run build:cssDatabase or migration changes also require a real PostgreSQL smoke test. Bot command changes require slash-command registration verification. A passing test suite does not prove that live Discord, Nitrado, GitHub, or container connectivity is configured correctly.
# Current container state
docker compose ps
# Recent bounded logs
docker compose logs --since=10m backend bot
# Rebuild after pulling reviewed changes
docker compose up -d --build backend bot
# Optional interactive admin TUI
docker compose --profile tools run --rm tuiThe TUI is deliberately excluded from the default service set. Back up PostgreSQL and provider-managed files before migrations or destructive operations.
- Discord OAuth authenticates browser users; live Discord membership and scoped roles authorize tenant operations.
- State-changing browser requests use CSRF protection.
- Nitrado, GitHub, and personal AI-provider credentials are encrypted at rest and remain server-side.
- The backend applies exact-guild and exact-server authorization to sensitive routes.
- Provider writes are not blindly retried.
- Production requires HTTPS cookies and rate limiting.
- Secrets, private history, operational logs, database exports, real player data, and credentials do not belong in the public repository.
Report vulnerabilities privately as described in SECURITY.md.
Map tile binaries are intentionally not included in this repository. The map UI expects operator-supplied tiles under:
public/maps/<map-name>/tiles/<x>/<y>.png
Only host tiles you are legally permitted to use and redistribute. See public/maps/README.md for the expected layout. The rest of the application can be developed and tested without committing tile binaries.
server.js Express application entry point
scheduler.js Scheduled log, economy, feed, and maintenance jobs
routes/ HTTP route handlers
services/ Shared business logic
middleware/ Authentication, authorization, CSRF, and rate limits
workers/ Background feed processing
bot/ Separate Discord bot package and process
db/ PostgreSQL schema and migrations
public/ HTML, browser JavaScript, and compiled CSS
styles/ Tailwind CSS source
scripts/ Tests, checks, setup, and operational utilities
templates/ Optional user-owned automation kits
Additional documentation:
- Contributor guide
- Agent/project architecture
- External integrations
- Database notes
- Migration notes
- Multi-tenant authorization
- DayZ loot system
- GitHub Actions automation kit
- Release history
Issues and focused pull requests are welcome. Read CONTRIBUTING.md and AGENTS.md before changing code. Do not include credentials, real provider identifiers, private infrastructure details, player data, production logs, database exports, or map-tile binaries in contributions.
- Website: https://saltskrew.xyz
- Discord: https://discord.gg/KJyRgfej7H
These links help fund development and operation of S.A.L.T. Some are referral links that may provide a benefit or commission to the project owner.
- Patreon
- Website hosting referral
- NordVPN referral
- BTC:
bc1qeun5ap3lgel3q6wel3vxpmvjgu2d5lp6gauxk3— Coinbase referral link - ETH:
0x33b68886ad3416c7f33c4a24a29731fcf7c18141— Coinbase referral link
S.A.L.T. is licensed under the GNU Affero General Public License v3.0 or later. Bundled third-party browser assets retain their own notices in THIRD_PARTY_NOTICES.md.