Documentation
Everything you need to deploy, configure, and extend Bastion.
Getting Started
Bastion is designed to be easy to self-host. The quickest way to get started is with Docker Compose, which sets up the entire stack — backend, database, and cache — in a single command.
git clone https://github.com/Calmingstorm/bastion.git
cd bastion
cp .env.example .env # Edit with your settings
docker compose up -d
That's it! Open http://localhost:8080 in your browser to access your Bastion instance. The first user to register becomes the server owner.
Requirements
Minimum requirements for self-hosting:
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 1 core | 2+ cores |
| RAM | 512 MB | 1+ GB |
| Storage | 1 GB | 10+ GB (for file uploads) |
| Docker | 20.10+ | Latest |
| Docker Compose | v2.0+ | Latest |
Bastion runs well on budget VPS providers like Linode, DigitalOcean, or Hetzner. A $5/month instance is sufficient for small communities.
Installation
Detailed installation steps:
1. Clone the repository
git clone https://github.com/Calmingstorm/bastion.git cd bastion
2. Configure environment
cp .env.example .env
Edit .env with your preferred settings. At minimum, change JWT_SECRET to a random string. See Configuration for all options.
3. Start the stack
docker compose up -d
4. Verify
# Check all containers are running docker compose ps # View logs docker compose logs -f bastion
Configuration
Bastion is configured via environment variables. Here are the key options:
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | — | PostgreSQL connection string |
REDIS_URL | — | Redis connection string |
JWT_SECRET | — | Secret for JWT token signing (required) |
PORT | 8080 | HTTP server port |
UPLOAD_MAX_SIZE | 25MB | Maximum file upload size |
UPLOAD_DIR | ./uploads | File upload storage path |
S3_ENDPOINT | — | S3-compatible storage endpoint (optional) |
S3_BUCKET | — | S3 bucket name |
S3_ACCESS_KEY | — | S3 access key |
S3_SECRET_KEY | — | S3 secret key |
CORS_ORIGINS | * | Allowed CORS origins (comma-separated) |
LOG_LEVEL | info | Logging level (debug, info, warn, error) |
Reverse Proxy
For production deployments, use a reverse proxy with automatic HTTPS. Here's a recommended Caddy configuration:
chat.yourdomain.com { reverse_proxy localhost:8080 }
Nginx alternative:
server { server_name chat.yourdomain.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } }
Bot Development
Bastion supports bots with a familiar API. Create a bot user in your server settings, then use the bot token to authenticate API requests.
Creating a Bot
- Go to Server Settings → Bots
- Click "Create Bot"
- Give it a name and save
- Copy the bot token (keep it secret!)
Example: Sending a Message
import requests TOKEN = "your-bot-token" BASE_URL = "https://your-instance.com/api/v1" # Send a message to a channel response = requests.post( f"{BASE_URL}/channels/{channel_id}/messages", headers={"Authorization": f"Bot {TOKEN}"}, json={"content": "Hello from my bot!"} )
Slash Commands
Register slash commands via the API, then handle interactions via your configured webhook endpoint:
# Register a slash command requests.post( f"{BASE_URL}/applications/{app_id}/commands", headers={"Authorization": f"Bot {TOKEN}"}, json={ "name": "ping", "description": "Check if the bot is alive", "type": 1 } )
API Overview
Bastion exposes a RESTful API at /api/v1/. All endpoints accept and return JSON. Authentication is via Bearer token in the Authorization header.
Key Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /auth/register | Create a new account |
POST | /auth/login | Get access token |
GET | /users/@me | Get current user |
GET | /guilds | List user's servers |
POST | /guilds | Create a server |
GET | /channels/{id}/messages | Get channel messages |
POST | /channels/{id}/messages | Send a message |
GET | /guilds/{id}/members | List server members |
GET | /guilds/{id}/roles | List server roles |
WebSocket connections for real-time events are established at /ws with a valid access token.
Webhooks
Webhooks let you send messages to channels from external services without a bot user. Create a webhook in channel settings, then POST to the webhook URL:
curl -X POST "https://your-instance.com/api/v1/webhooks/{id}/{token}" \ -H "Content-Type: application/json" \ -d '{"content": "Deployment successful!", "username": "CI Bot"}'
Troubleshooting
Container won't start
Check logs with docker compose logs bastion. Common issues: missing environment variables (especially JWT_SECRET), database not ready yet (restart with docker compose restart bastion).
WebSocket connection fails
If using a reverse proxy, ensure WebSocket upgrade headers are passed through. See the Reverse Proxy section for correct configuration.
File uploads not working
Ensure the UPLOAD_DIR exists and is writable by the container. If using S3, verify your credentials and bucket permissions.
Database migration errors
Migrations run automatically on startup. If they fail, check that your PostgreSQL version is 14+ and the database user has CREATE TABLE permissions.