Deploying a Gotify App
Introduction
Gotify is a powerful, open-source self-hosted notification server written in Go that enables you to send and receive push notifications in real-time. Whether you’re building automated alerting systems, monitoring infrastructure, or creating custom notification workflows, Gotify provides a simple REST API and WebSocket support for seamless integration with your applications and services.
Deploying Gotify on Klutch.sh gives you a managed, scalable platform for running your notification server with automatic HTTPS, persistent storage for your messages and users, and easy configuration through environment variables. This comprehensive guide walks you through deploying Gotify using a Dockerfile, configuring persistent volumes for data retention, setting up security, and managing your notification server in production.
Prerequisites
- A Klutch.sh account (sign up here)
- A GitHub repository for your Gotify deployment
- Basic familiarity with Docker and environment variables
- (Optional) A custom domain for your notification server
What You’ll Deploy
- Inputs: GitHub repository with a Dockerfile for Gotify
- Outputs: Running Gotify notification server on Klutch.sh accessible over HTTPS
- Success Criteria: Web UI loads, you can create applications and tokens, send test notifications via API, and data persists across restarts
Key features:
- Real-time push notifications via WebSocket
- Simple REST API for sending messages
- User and application management
- Message history with persistent storage
- Mobile app support (Android)
Getting Started: Understanding Gotify
Gotify consists of a web UI for managing applications and viewing notifications, and a REST API for sending messages. The server stores all data (users, applications, messages) in an SQLite database by default, making it lightweight and easy to manage.
Key Concepts
- Applications: Represent services that send notifications (e.g., monitoring system, CI/CD pipeline)
- Clients: Devices or browsers that receive notifications
- Messages: The actual notifications with title, content, and priority
- Tokens: API keys used to authenticate applications and clients
1. Prepare Your Repository
Create a new GitHub repository for your Gotify deployment. You have two deployment options:
Option A: Without Dockerfile (Nixpacks)
- Use Klutch.sh’s automatic build detection
- No Dockerfile needed
- Ideal for quick deployments
Option B: With Dockerfile
- More control over build process
- Pinned versions for reproducibility
- Custom configuration in Dockerfile
Minimal repository structure for either approach:
gotify-deploy/├── Dockerfile (optional, for manual Docker deployments)├── config.yml (optional)└── README.mdFor a quick start without Dockerfile, you only need a README and optionally a configuration file. Klutch.sh will automatically use the official Gotify Docker image via Nixpacks.
2. Deploying Without a Dockerfile (Using Nixpacks)
Klutch.sh uses Nixpacks to automatically detect and deploy Gotify. This method is perfect for getting started quickly without managing a custom Dockerfile.
Prepare Your Repository for Nixpacks
For Nixpacks to detect and deploy Gotify, your repository needs:
- A
README.mdfile at the repository root - Optionally, a
config.ymlfile in the root directory for custom configuration
Example minimal repository structure:
gotify-deploy/├── README.md├── config.yml (optional)└── .gitignoreExample README.md:
# Gotify Notification Server
Self-hosted notification server deployed on Klutch.sh.
## Configuration
Configure Gotify through environment variables in Klutch.sh dashboard:- `GOTIFY_DEFAULTUSER_PASS` - Admin password- `GOTIFY_REGISTRATION` - Enable/disable user registration- `GOTIFY_MESSAGERETENTION` - Message retention in days
## Documentation
See the deployment guide for complete setup instructions.Deploy via Nixpacks
- Push repository to GitHub
- Ensure your repository has a README.md
- Add any configuration files you want to track
- Commit and push to your GitHub repository
- Log in to Klutch.sh
- Navigate to klutch.sh/app
- Create a new project
- Click Create Project
- Give it a descriptive name (e.g., "Notification Server")
- Create a new app
- Click Create App
- Connect your GitHub repository
- Select the branch to deploy (usually
mainormaster)
- Configure the app settings
- Traffic Type: Select HTTP
- Internal Port: Set to
80(Gotify's default port) - Region: Choose your preferred region
- Compute: Start with a small instance (Gotify is lightweight)
- Instances: 1 instance is sufficient
- Attach persistent volume
- Add a volume with mount path
/app/data - Set size to at least 1GB
- Add a volume with mount path
- Add environment variables
- Set the variables listed in section 4 of this guide
- Mark sensitive values as secrets
- Important: Change the default admin password from "admin" to a strong password
- Deploy
- Click "Create" to start the deployment
- Klutch.sh will build and deploy Gotify automatically
- Monitor the build logs for any errors
Advantages of Nixpacks deployment:
- No need to manage a Dockerfile
- Automatic updates to the Gotify image
- Simpler repository structure
- Faster setup for new deployments
3. Deploying With a Dockerfile
Gotify provides an official Docker image that’s production-ready. Create a Dockerfile in your repository root:
# Use the official Gotify imageFROM gotify/server:latest
# The official image handles everything needed# Data is stored in /app/data# Configuration can be provided via environment variables or config.yml
# Expose the default Gotify portEXPOSE 80
# The base image already sets the correct CMD# It runs: ./gotify-appThis minimal Dockerfile uses the official Gotify image which includes:
- The compiled Gotify server binary
- Default configuration
- Web UI assets
- SQLite database support
Advanced Dockerfile with Specific Version
For production environments, it’s recommended to pin a specific version:
# Pin to a specific Gotify version for reproducible buildsFROM gotify/server:2.4.0
# Expose port 80 (Gotify default)EXPOSE 80
# Optional: Set default environment variables# These can be overridden in Klutch.shENV GOTIFY_SERVER_PORT=80ENV GOTIFY_SERVER_KEEPALIVEPERIODSECONDS=0ENV GOTIFY_SERVER_LISTENADDR=""ENV GOTIFY_SERVER_SSL_ENABLED=false
# The base image CMD is already set correctlyNote: Klutch.sh automatically detects the Dockerfile in your repository root and uses it for deployment.
4. Persistent Storage Configuration
Gotify stores all data in the /app/data directory inside the container, including:
- SQLite database (
gotify.db) - User accounts and passwords
- Application tokens
- Message history
- Uploaded images
To prevent data loss when redeploying, you must attach a persistent volume.
Volume Configuration in Klutch.sh
When creating your app in Klutch.sh:
- Navigate to your app settings
- Go to the "Volumes" section
- Click "Add Volume"
- Configure the volume:
- Mount Path:
/app/data - Size: Start with 1GB (adjust based on message retention needs)
- Mount Path:
- Save the volume configuration
Important: The volume must be attached before first deployment to ensure the default admin user credentials are persisted.
5. Environment Variables and Configuration
Gotify can be configured through environment variables or a config.yml file. For Klutch.sh deployments, environment variables are the recommended approach.
Essential Environment Variables
Add these in the Klutch.sh dashboard under your app’s environment variables:
# Server ConfigurationGOTIFY_SERVER_PORT=80GOTIFY_SERVER_LISTENADDR=""
# Database (SQLite is default, stored in /app/data)GOTIFY_DATABASE_DIALECT=sqlite3GOTIFY_DATABASE_CONNECTION=/app/data/gotify.db
# Security - IMPORTANT: Replace with your actual domain in production# Example: GOTIFY_SERVER_STREAM_ALLOWEDORIGINS="https://example-app.klutch.sh"GOTIFY_SERVER_STREAM_ALLOWEDORIGINS="https://example-app.klutch.sh"Optional Environment Variables
# Default admin credentials (set a strong password before deployment)GOTIFY_DEFAULTUSER_NAME=adminGOTIFY_DEFAULTUSER_PASS=your-secure-password-here
# Registration (disable in production)GOTIFY_REGISTRATION=false
# Upload limitsGOTIFY_UPLOADEDIMAGESDIR=/app/data/imagesGOTIFY_MAXMESSAGESIZE=2048
# WebSocket keepaliveGOTIFY_SERVER_KEEPALIVEPERIODSECONDS=45
# Message retention (in days, 0 = unlimited)GOTIFY_MESSAGERETENTION=90Security Note: Never commit secrets to your repository. Always use Klutch.sh’s environment variable management and mark sensitive values as secret.
6. Deploying to Klutch.sh
Follow these steps to deploy Gotify on Klutch.sh:
- Push your repository to GitHub
- Ensure your
Dockerfileis in the root directory - Commit and push all changes
- Ensure your
- Log in to Klutch.sh
- Navigate to klutch.sh/app
- Create a new project
- Click Create Project
- Give it a descriptive name (e.g., "Notification Server")
- Create a new app
- Click Create App
- Connect your GitHub repository
- Select the branch to deploy (usually
mainormaster)
- Configure the app settings
- Traffic Type: Select HTTP
- Internal Port: Set to
80(Gotify's default port) - Region: Choose your preferred region
- Compute: Start with a small instance (Gotify is lightweight)
- Instances: 1 instance is sufficient for most use cases
- Attach persistent volume
- Add a volume with mount path
/app/data - Set size to at least 1GB
- Add a volume with mount path
- Add environment variables
- Add the essential environment variables listed in section 4
- Mark sensitive values as secrets
- Important: Change the default admin password from "admin" to a strong password
- Deploy
- Click "Create" to start the deployment
- Klutch.sh will build your Docker image and start the container
- Monitor the build logs for any errors
Once deployment completes, your Gotify server will be available at example-app.klutch.sh (replace with your actual app URL).
7. Initial Setup and Configuration
After your first deployment:
- Access the Web UI
- Navigate to your app URL (e.g.,
https://example-app.klutch.sh) - You'll see the Gotify login page
- Navigate to your app URL (e.g.,
- Log in with your credentials
- Username:
admin(or the value you set inGOTIFY_DEFAULTUSER_NAME) - Password: The secure password you set in
GOTIFY_DEFAULTUSER_PASS
- Username:
- Change the admin password immediately
- Click on "Users" in the sidebar
- Click the edit icon for the admin user
- Set a strong password
- Save changes
- Create your first application
- Click "Apps" in the sidebar
- Click "Create Application"
- Give it a name (e.g., "Test App")
- Optionally set a description and upload an icon
- Save the application
- Important: Copy the generated token immediately (you won't be able to see it again)
- Send a test notification
- Use curl or any HTTP client:
curl -X POST "https://example-app.klutch.sh/message" \ -H "X-Gotify-Key: YOUR_APP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "Test Notification", "message": "Hello from Klutch.sh!", "priority": 5 }'You should see the notification appear in the web UI immediately.
8. Using the Gotify API
Gotify provides a simple REST API for sending messages and managing resources.
Send a Message
# Basic messagecurl -X POST "https://example-app.klutch.sh/message" \ -H "X-Gotify-Key: YOUR_APP_TOKEN" \ -H "Content-Type: application/json" \ -d '{"title": "Alert", "message": "Server CPU is high", "priority": 8}'
# Message with markdowncurl -X POST "https://example-app.klutch.sh/message" \ -H "X-Gotify-Key: YOUR_APP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "Deployment Status", "message": "**Deployment Successful**\n\n- Environment: Production\n- Version: v2.1.0\n- Duration: 3m 45s", "priority": 5, "extras": { "client::display": { "contentType": "text/markdown" } } }'Priority Levels
Gotify supports priority levels from 0 to 10:
- 0-3: Low priority (no sound/vibration)
- 4-7: Normal priority (default notification)
- 8-10: High priority (urgent, will notify even in do-not-disturb mode)
Get Messages
# Get all messages for your clientcurl "https://example-app.klutch.sh/message" \ -H "X-Gotify-Key: YOUR_CLIENT_TOKEN"
# Get messages with paginationcurl "https://example-app.klutch.sh/message?limit=10&since=0" \ -H "X-Gotify-Key: YOUR_CLIENT_TOKEN"Delete Messages
# Delete a specific messagecurl -X DELETE "https://example-app.klutch.sh/message/123" \ -H "X-Gotify-Key: YOUR_CLIENT_TOKEN"
# Delete all messages for an appcurl -X DELETE "https://example-app.klutch.sh/application/1/message" \ -H "X-Gotify-Key: YOUR_CLIENT_TOKEN"WebSocket Connection
Gotify supports real-time notifications via WebSocket:
// Connect to WebSocket endpointconst ws = new WebSocket('wss://example-app.klutch.sh/stream?token=YOUR_CLIENT_TOKEN');
ws.onmessage = (event) => { const message = JSON.parse(event.data); console.log('New notification:', message);};
ws.onerror = (error) => { console.error('WebSocket error:', error);};9. Integration Examples
Shell Script Notifications
#!/bin/bash# Send notification from a shell script
GOTIFY_URL="https://example-app.klutch.sh"GOTIFY_TOKEN="YOUR_APP_TOKEN"
send_notification() { local title="$1" local message="$2" local priority="${3:-5}"
curl -s -X POST "${GOTIFY_URL}/message" \ -H "X-Gotify-Key: ${GOTIFY_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"title\": \"${title}\", \"message\": \"${message}\", \"priority\": ${priority}}"}
# Usagesend_notification "Backup Complete" "Database backup finished successfully" 5Python Integration
import requestsimport json
class GotifyClient: def __init__(self, url, token): self.url = url.rstrip('/') self.token = token
def send_message(self, title, message, priority=5, extras=None): payload = { 'title': title, 'message': message, 'priority': priority }
if extras: payload['extras'] = extras
headers = { 'X-Gotify-Key': self.token, 'Content-Type': 'application/json' }
response = requests.post( f'{self.url}/message', headers=headers, data=json.dumps(payload) )
return response.json()
# Usageclient = GotifyClient('https://example-app.klutch.sh', 'YOUR_APP_TOKEN')client.send_message( 'Deployment Alert', 'Application deployed to production', priority=7)Node.js/JavaScript Integration
const axios = require('axios');
class GotifyClient { constructor(url, token) { this.url = url.replace(/\/$/, ''); this.token = token; }
async sendMessage(title, message, priority = 5, extras = null) { const payload = { title, message, priority, };
if (extras) { payload.extras = extras; }
try { const response = await axios.post( `${this.url}/message`, payload, { headers: { 'X-Gotify-Key': this.token, 'Content-Type': 'application/json', }, } ); return response.data; } catch (error) { console.error('Failed to send notification:', error.message); throw error; } }}
// Usageconst client = new GotifyClient('https://example-app.klutch.sh', 'YOUR_APP_TOKEN');client.sendMessage('Build Status', 'Build #142 completed successfully', 5);Monitoring Integration
Integrate Gotify with monitoring systems:
# Prometheus Alertmanager webhook receiver# Create a script that receives webhooks and forwards to Gotify
#!/bin/bash
GOTIFY_URL="https://example-app.klutch.sh"GOTIFY_TOKEN="YOUR_APP_TOKEN"
# Read alert from stdinALERT=$(cat)
# Parse alert details (simplified example)ALERT_NAME=$(echo "$ALERT" | jq -r '.alerts[0].labels.alertname')ALERT_DESCRIPTION=$(echo "$ALERT" | jq -r '.alerts[0].annotations.description')SEVERITY=$(echo "$ALERT" | jq -r '.alerts[0].labels.severity')
# Map severity to prioritycase $SEVERITY in critical) PRIORITY=10 ;; warning) PRIORITY=7 ;; *) PRIORITY=5 ;;esac
# Send to Gotifycurl -X POST "${GOTIFY_URL}/message" \ -H "X-Gotify-Key: ${GOTIFY_TOKEN}" \ -H "Content-Type: application/json" \ -d "{ \"title\": \"Alert: ${ALERT_NAME}\", \"message\": \"${ALERT_DESCRIPTION}\", \"priority\": ${PRIORITY} }"10. Security Best Practices
Protect your Gotify instance with these security measures:
- Change default credentials immediately
- Never use the default admin/admin credentials in production
- Use a strong, unique password
- Disable user registration
- Set
GOTIFY_REGISTRATION=falseto prevent unauthorized users from creating accounts - Create users manually through the admin interface
- Set
- Manage tokens securely
- Store API tokens in environment variables or secrets managers
- Never commit tokens to version control
- Rotate tokens periodically
- Delete unused application tokens
- Use HTTPS only
- Klutch.sh provides automatic HTTPS
- Never expose Gotify over plain HTTP in production
- Ensure all API calls use HTTPS URLs
- Limit CORS origins (Critical)
- Always specify exact origins for production:
GOTIFY_SERVER_STREAM_ALLOWEDORIGINS="https://example-app.klutch.sh"- Never use wildcard
"*"in production as it allows any domain to access your WebSocket stream - For multiple domains, use comma-separated values:
"https://domain1.com,https://domain2.com"
- Regular backups
- Back up the
/app/datavolume regularly - Test restore procedures periodically
- Back up the
- Monitor access logs
- Review Gotify logs in Klutch.sh dashboard
- Watch for suspicious authentication attempts
- Set up alerts for failed login attempts
- Keep Gotify updated
- Pin specific versions in your Dockerfile for stability
- Update regularly to get security patches
- Test updates in a staging environment first
11. Custom Domain Configuration
To use your own domain with Gotify:
- Add domain in Klutch.sh
- Navigate to your app settings
- Go to the "Domains" section
- Add your custom domain (e.g.,
notify.yourdomain.com) - See custom domains documentation for details
- Configure DNS
- Add a CNAME record pointing to your Klutch.sh app URL
- Or add an A record with the provided IP address
- Update environment variables
- No need to change
GOTIFY_SERVER_PORTor internal settings - Update any hardcoded URLs in your application code
- No need to change
- Wait for DNS propagation
- DNS changes may take up to 48 hours to propagate
- Klutch.sh will automatically provision SSL certificates
12. Monitoring and Maintenance
Monitor Your Gotify Instance
- Check application health
- Use the health endpoint:
curl https://example-app.klutch.sh/health - Expected response:
{"health":"green","database":"green"}
- Use the health endpoint:
- Monitor resource usage
- Check CPU and memory usage in Klutch.sh dashboard
- Gotify is lightweight; issues usually indicate configuration problems
- Review logs
- Access logs through Klutch.sh dashboard
- Look for error messages or failed authentication attempts
- Database maintenance
- Set
GOTIFY_MESSAGERETENTIONto auto-delete old messages - Monitor volume usage to prevent disk space issues
- Consider periodic database vacuuming for SQLite:
VACUUM;
- Set
Scaling Considerations
Gotify is designed to be lightweight and efficient:
- Single instance: Sufficient for most use cases (thousands of messages per day)
- Database: SQLite is appropriate unless you need high concurrency
- Volume size: Monitor message storage; increase volume size if needed
- Connection limits: WebSocket connections are lightweight; one instance can handle hundreds of concurrent clients
If you need higher availability:
- Use a staging environment to test changes
- Implement backup/restore procedures
- Consider PostgreSQL for high-concurrency scenarios (requires custom configuration)
13. Troubleshooting
Common Issues and Solutions
Issue: Cannot access the web UI (502/503 errors)
- Solution: Check that:
- The internal port is set to 80
- Traffic type is HTTP
- The app has finished deploying (check build logs)
- Environment variables are set correctly
Issue: Data lost after redeployment
- Solution: Ensure persistent volume is attached to
/app/databefore first deployment - If volume was added later, you'll need to reconfigure from scratch
Issue: Authentication fails with “invalid username or password”
- Solution:
- Verify you're using the correct credentials
- Check if
GOTIFY_DEFAULTUSER_NAMEandGOTIFY_DEFAULTUSER_PASSare set correctly - If locked out, you may need to reset the database (this will lose all data)
Issue: API requests return 401 Unauthorized
- Solution:
- Verify your API token is correct
- Check that the token hasn't been deleted or regenerated
- Ensure the
X-Gotify-Keyheader is properly set - Confirm you're using an application token for sending messages, not a client token
Issue: WebSocket connection fails
- Solution:
- Check CORS settings:
GOTIFY_SERVER_STREAM_ALLOWEDORIGINS - Verify you're using
wss://(secure WebSocket) notws:// - Ensure client token is valid
- Check browser console for error messages
- Check CORS settings:
Issue: High memory usage
- Solution:
- Check message retention settings
- Delete old messages you no longer need
- Consider setting
GOTIFY_MESSAGERETENTIONto auto-delete - Review the number of open WebSocket connections
Issue: Database is locked errors
- Solution:
- Ensure only one Gotify instance is accessing the database
- Check for crashed processes holding database locks
- Restart the application if necessary
Debug Commands
Access your container logs in Klutch.sh dashboard to diagnose issues:
# Test API connectivitycurl -I https://example-app.klutch.sh/health
# Test authenticationcurl -X GET "https://example-app.klutch.sh/current/user" \ -H "X-Gotify-Key: YOUR_CLIENT_TOKEN"
# List all applicationscurl -X GET "https://example-app.klutch.sh/application" \ -H "X-Gotify-Key: YOUR_CLIENT_TOKEN"14. Backup and Disaster Recovery
Implement a backup strategy to protect your notification data:
Backup Strategy
- What to back up:
/app/data/gotify.db- SQLite database (users, apps, messages)/app/data/images/- Uploaded images and icons- Environment variables and configuration
- Backup frequency:
- Daily backups for production systems
- Keep 7-30 days of backups depending on retention needs
- Back up before any major changes or updates
- Backup methods:
- Volume snapshots through Klutch.sh (if available)
- Database exports using SQLite tools
- File-based backups of the entire
/app/datadirectory
Manual Database Backup
# If you have access to the container, backup the database:sqlite3 /app/data/gotify.db ".backup /app/data/gotify-backup-$(date +%Y%m%d).db"
# Export as SQLsqlite3 /app/data/gotify.db .dump > gotify-backup-$(date +%Y%m%d).sqlDisaster Recovery Steps
- Create a new Gotify deployment following the deployment steps
- Stop the new instance before restoring data
- Restore the database to
/app/data/gotify.db - Restore images to
/app/data/images/ - Start the instance and verify all data is present
- Test functionality:
- Log in with existing credentials
- Verify applications and tokens are present
- Send a test message
- Check message history
15. Production Deployment Checklist
Before deploying Gotify to production, verify:
- Dockerfile is using a pinned version (e.g.,
gotify/server:2.4.0) - Persistent volume attached to
/app/datawith adequate size - Default admin password changed to a strong, unique password
- User registration disabled (
GOTIFY_REGISTRATION=false) - CORS origins restricted to specific domains
- Message retention policy configured (
GOTIFY_MESSAGERETENTION) - HTTPS enabled (automatic with Klutch.sh)
- Custom domain configured (if applicable)
- Environment variables properly set and secrets marked as such
- Backup strategy implemented and tested
- Monitoring configured for health checks
- API tokens generated and securely stored
- Test notifications sent successfully
- WebSocket connections working
- Mobile app connected (if using Android app)
- Integration with monitoring/alerting systems tested
- Documentation created for team members
16. Additional Resources
Official Documentation
- Gotify Official Documentation
- Message Extras and Formatting
- Configuration Options
- Gotify GitHub Repository
Klutch.sh Resources
Mobile Apps
Community and Support
Conclusion
Deploying Gotify on Klutch.sh provides you with a powerful, self-hosted notification system with the reliability and scalability of a managed platform. With persistent storage, automatic HTTPS, and easy configuration through environment variables, you can have a production-ready notification server running in minutes.
Whether you’re sending alerts from monitoring systems, CI/CD pipelines, or custom applications, Gotify’s simple API and real-time WebSocket support make it an excellent choice for managing notifications across your infrastructure.
Start by deploying the basic setup, test with a few applications, and gradually expand your integration as you become familiar with the platform. Don’t forget to implement security best practices and regular backups to ensure your notification system remains reliable and secure.