See the Installation Guide for binary download, database setup, systemd, and reverse proxy instructions. This guide focuses on configuration and day-to-day administration.
First registered user (automatic admin)
When the user table is empty, the account created by the first successful self-registration is given the admin global role automaticallyβno SQL or manual promotion step.
Additional administrators can be assigned later from Admin panel β Users.
Recovering admin access
If every administrator has been demoted or deactivated and you are locked out, restore access with a direct database update (use the accountβs username, not its numeric id):
# SQLite
sqlite3 warmdesk.db "UPDATE users SET global_role='admin' WHERE username='yourname';"
# PostgreSQL
psql -U warmdesk -c "UPDATE users SET global_role='admin' WHERE username='yourname';"
# MySQL (adjust user and database name to match `db_dsn` in warmdesk.yaml)
mysql -u warmdesk -p -e "UPDATE users SET global_role='admin' WHERE username='yourname';" warmdeskRestarting the server is optional after manual fixes like these.
Global roles
| Role | Capabilities |
|---|---|
| Full access to all projects, customers, users, and system settings |
| Can create projects, manage their own projects, access assigned resources |
| Read-only access to assigned projects and customers |
| Read-only access to the Prometheus |
| Can trigger and download backups via the API |
Within each project, users have a project role (owner, member, viewer) that is independent of their global role. Admin users bypass all project-level checks.
Admin panel
Access the admin panel from the sidebar (admin users only). It contains:
Users tab
Create new user accounts (for when self-registration is disabled)
Edit name, email, and global role
Deactivate or reactivate accounts
Reset a userβs MFA (TOTP)
View last login time and last password change
Groups tab
Define user groups and assign them to projects and customers. Assigning a group to a project gives all group members the specified project role. This is useful for onboarding an entire team at once.
Projects tab
View all projects, including archived ones
Archive, restore, or permanently delete projects
Change project ownership
System settings tab
See the System Settings section below.
System settings
System settings are stored as key/value rows in the database and take effect immediately without a restart. Configure them from Admin β System Settings.
SMTP (email)
| Setting | Description |
|---|---|
SMTP host | Mail server hostname |
SMTP port | Usually 587 (STARTTLS) or 465 (TLS) |
SMTP username / password | Mail server credentials |
From address |
|
TLS mode |
|
Test the SMTP configuration with the Send test email button.
Registration and sessions
Allow public registration β enable or disable self-registration on the login page
Session timeout β idle minutes before a user is logged out (0 = no timeout)
Password max age β days before a password expires (0 = never); users with expired passwords are redirected to Settings on login
Branding
Company name β shown in the page title and emails
Company logo β PNG/SVG displayed on the login page and in the header
Locale defaults
Default language, date format, and timezone for new users. Users can override these in their own settings.
Password policy
| Setting | Description |
|---|---|
Minimum length | Default: 8 characters |
Max age (days) | Days before password expires; 0 disables expiry |
Bcrypt cost | Fixed at 12 (compile-time constant; change requires a rebuild) |
SMTP troubleshooting
Verify host, port, credentials, and TLS mode in System Settings
Use the Send test email button to confirm delivery
Check firewall rules for outbound port 587/465
If using Gmail, create an App Password (regular passwords are blocked)
Backup and recovery
Via the admin panel
Go to Admin β Backup. Click Create backup to generate a ZIP containing the database dump and uploaded files. Download the ZIP for off-site storage. To restore, upload the ZIP and click Restore.
Warning | Restoring from backup replaces all current data. Take a fresh backup before restoring. |
Via the API (automation)
Use a personal API key with the backup role:
# Create a backup and download it
curl -H "X-API-Key: your-key" \
https://warmdesk.example.com/api/v1/admin/backup \
-o backup-$(date +%Y%m%d).zipSchedule with cron for automated nightly backups.
SQLite β manual backup
# Safe hot backup using SQLite's backup API
sqlite3 warmdesk.db ".backup /backup/warmdesk-$(date +%Y%m%d).db"Security hardening
Startup safety checks
WarmDesk refuses to start if:
jwt_secretis still the default valuechange-me-in-productiongin_modeisreleaseandallowed_originscontains*
Security checklist
β
jwt_secretis a long random stringβ
gin_mode: releasein productionβ
allowed_originslists only your actual domain(s)β
db_tls_mode: verify-fullfor remote databasesβ TLS terminated at the reverse proxy
β Port 8080 not exposed to the internet (firewall)
β
upload_diris outside the web rootβ Backups are scheduled and regularly tested
β MFA enforced for admin accounts
β Asciidoctor
safeModeset tounsafeonly in trusted deployments
Known limitations
The in-process rate limiter is per-instance. In a multi-instance deployment, each instance has its own counter β a distributed brute-force attack can bypass the limit. Use a WAF or rate-limiting proxy for multi-instance deployments.
In the desktop (Tauri) app, JWT tokens are stored in
sessionStorage(accessible to JavaScript). A proper fix requires routing API calls through the Rust layer β not yet implemented.
Horizontal scaling
Run multiple WarmDesk instances behind a load balancer:
redis_url: redis://redis-host:6379/0
db_driver: postgres
db_dsn: host=pg-primary user=warmdesk password=secret dbname=warmdesk sslmode=requireRequirements:
All instances share the same PostgreSQL or MySQL database
Redis is required for WebSocket pub/sub across instances
Sticky sessions are not required β WebSocket connections are handled per-instance and bridged via Redis
Ansible deployment
An Ansible collection is available on Ansible Galaxy:
ansible-galaxy collection install ansilabnl.warmdeskThe collection installs the binary, creates a systemd unit, and configures nginx. See the collection README for variables and an example playbook.
Updating
Download the new binary
Stop the service:
systemctl stop warmdeskReplace the binary
Start the service:
systemctl start warmdesk
Schema migrations run automatically on startup via GORM AutoMigrate. No manual SQL migration steps are needed.
Demo data
A script in the repository populates the database with sample projects, cards, and users for demonstration purposes:
cd backend
go run scripts/demo_data.goPrometheus metrics
GET /api/v1/metrics exposes a standard Prometheus scrape endpoint.
Accessible to users with the metrics or admin global role.
# prometheus.yml snippet
scrape_configs:
- job_name: warmdesk
bearer_token: your-metrics-api-key
static_configs:
- targets: ['warmdesk.example.com:443']
scheme: https