Deploy Tux using Docker Compose - the recommended method for most users.
Overview
Docker Compose deployment includes:
- Tux Bot - Main Discord bot container
- PostgreSQL - Database (postgres:17-alpine)
- Adminer - Web-based database management UI
All services are pre-configured and ready to use.
Prerequisites
Required
- Docker - Install Docker
- Docker Compose - Usually included with Docker Desktop
- Git - For cloning repository
- Discord Bot Token - How to get one
Verify Installation
docker --version # Should show Docker 20.10+
docker compose version # Should show Compose 2.0+
git --version # Should show Git 2.0+
Quick Start
1. Clone Repository
git clone https://github.com/allthingslinux/tux.git
cd tux
2. Configure Environment
# Generate example config
uv run config generate
# Or manually copy
cp config/config.toml.example config/config.toml
Create .env
file (it's git-ignored):
cat > .env << 'EOF'
# Discord Configuration
BOT_TOKEN=your_discord_bot_token_here
# Database Configuration (defaults are fine for Docker)
POSTGRES_DB=tuxdb
POSTGRES_USER=tuxuser
POSTGRES_PASSWORD=ChangeThisToAStrongPassword123!
# Environment
ENVIRONMENT=production
DEBUG=false
# Optional: Sentry
# SENTRY_DSN=https://your-sentry-dsn
# Optional: InfluxDB
# EXTERNAL_SERVICES__INFLUXDB_URL=http://influxdb:8086
# EXTERNAL_SERVICES__INFLUXDB_TOKEN=your_token
# EXTERNAL_SERVICES__INFLUXDB_ORG=your_org
EOF
Edit the .env
file with your actual bot token.
3. Start Services
# Start all services in detached mode
docker compose up -d
# View logs
docker compose logs -f tux
4. Verify Running
# Check service status
docker compose ps
# Should show:
# tux running
# tux-postgres running (healthy)
# tux-adminer running
5. Invite Bot
Invite Tux to your Discord server using your bot's OAuth2 URL.
6. Run Setup Wizard
In your Discord server:
/config wizard
Done! Tux is now running.
Services
Tux Bot
Main Discord bot service:
- Container:
tux
- Image:
ghcr.io/allthingslinux/tux:latest
(or builds locally) - Ports: None (Discord connection only)
- Volumes:
config/
- Configuration files (read-only)assets/
- Images and assets (read-only)src/tux/plugins/
- Custom plugins (read-only)src/tux/database/migrations/
- Database migrationstux_cache
- Cache datatux_temp
- Temporary filestux_user_home
- User home directory
Health Check: Runs every 30s, checks config and bot token
Restart Policy: unless-stopped
(always restart except manual stop)
PostgreSQL
Database service:
- Container:
tux-postgres
- Image:
postgres:17-alpine
- Port:
5432
(exposed to host) - Volume:
tux_postgres_data
(persistent storage) - Configuration: Custom
postgresql.conf
for optimization
Health Check: pg_isready
every 10s
Restart Policy: no
(manual restart only)
Adminer
Web-based database administration:
- Container:
tux-adminer
- Image:
adminer:latest
- Port:
8080
(default, configurable viaADMINER_PORT
) - URL:
http://localhost:8080
- Theme: Dracula
Auto-login: Enabled by default (development only!)
Docker Compose Commands
Starting Services
# Start all services
docker compose up -d
# Start and view logs
docker compose up
# Start specific service
docker compose up -d tux
Stopping Services
# Stop all services
docker compose down
# Stop but keep data
docker compose stop
# Stop and remove volumes (WARNING: deletes data!)
docker compose down -v
Viewing Logs
# All services
docker compose logs -f
# Specific service
docker compose logs -f tux
docker compose logs -f tux-postgres
# Last N lines
docker compose logs --tail=100 tux
# Since timestamp
docker compose logs --since 2024-01-01T00:00:00 tux
Updating
# Pull latest code
git pull
# Rebuild and restart
docker compose up -d --build
# Run new migrations
docker compose exec tux uv run db push
Database Operations
# Run migrations
docker compose exec tux uv run db push
# Check database health
docker compose exec tux uv run db health
# List tables
docker compose exec tux uv run db tables
# Access psql
docker compose exec tux-postgres psql -U tuxuser -d tuxdb
Debugging
# Execute command in container
docker compose exec tux uv run tux version
# Open shell in container
docker compose exec tux /bin/bash
# View container details
docker compose ps
docker inspect tux
Configuration
Environment Variables
Key environment variables in .env
:
# Required
BOT_TOKEN=your_token
# Database (defaults work for Docker)
POSTGRES_HOST=tux-postgres # Container name
POSTGRES_DB=tuxdb
POSTGRES_USER=tuxuser
POSTGRES_PASSWORD=strong_password
# Optional
DEBUG=false # Enable debug logging
ENVIRONMENT=production # Environment name
USE_LOCAL_MIGRATIONS=true # Use local migration files
FORCE_MIGRATE=false # Force migration on startup
Custom Configuration
Place config files in config/
:
config/config.toml
- TOML configurationconfig/config.yaml
- YAML configurationconfig/config.json
- JSON configuration
These are mounted read-only into the container.
Volumes Explained
Configuration Volumes (Read-Only):
./config:/app/config:ro
- Your config files./assets:/app/assets:ro
- Bot assets (images, etc.)./src/tux/plugins:/app/tux/plugins:ro
- Custom plugins
Data Volumes (Persistent):
tux_postgres_data
- PostgreSQL datatux_cache
- Bot cachetux_temp
- Temporary filestux_user_home
- Container user home
Development Mode
Docker Compose includes development features:
File Watching
# Start with file watching (hot-reload)
docker compose watch
# Code changes sync automatically
# Bot reloads on change (if hot-reload enabled in code)
What's watched:
./src
- Source code (syncs)./config
- Config files (syncs)./assets
- Assets (syncs)pyproject.toml
- Rebuild on change.env
- Restart on change
Development vs Production
Development:
# Use watch mode
docker compose watch
# Or with debug logging
DEBUG=true docker compose up
Production:
# Standard detached mode
docker compose up -d
# Use prebuilt image
TUX_IMAGE=ghcr.io/allthingslinux/tux TUX_IMAGE_TAG=v1.0.0 docker compose up -d
Adminer Web UI
Access database via web interface:
Accessing Adminer
- Open browser:
http://localhost:8080
- Auto-login enabled (development)
- Or manual login:
- System: PostgreSQL
- Server: tux-postgres
- Username: tuxuser
- Password: (from your .env)
- Database: tuxdb
Features
- Browse tables
- Run SQL queries
- Export/import data
- View table structure
- Edit data directly
Security Warning
Disable Auto-Login in Production
The default configuration has auto-login enabled for development convenience.
For production, set ADMINER_AUTO_LOGIN=false
in .env
.
Customization
Change Adminer port:
# In .env
ADMINER_PORT=9090
Then access at http://localhost:9090
Production Deployment
Security Hardening
- Change Default Password:
bash
POSTGRES_PASSWORD="$(openssl rand -base64 32)"
- Disable Adminer Auto-Login:
bash
ADMINER_AUTO_LOGIN=false
- Don't Expose Ports:
yaml
# In compose.yaml, comment out port mappings:
# ports: ['${POSTGRES_PORT:-5432}:5432']
- Use Secrets:
bash
chmod 600 .env
Resource Limits
Add resource limits to compose.yaml
:
services:
tux:
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
Logging
Configure log rotation:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
compress: "true"
Already configured in the default compose.yaml
.
Backups
Database Backup
# Create backup
docker compose exec tux-postgres pg_dump -U tuxuser tuxdb > backup_$(date +%Y%m%d).sql
# With compression
docker compose exec tux-postgres pg_dump -U tuxuser tuxdb | gzip > backup_$(date +%Y%m%d).sql.gz
# Automated daily backup script
cat > backup.sh << 'EOF'
#!/bin/bash
docker compose exec tux-postgres pg_dump -U tuxuser tuxdb | gzip > backups/backup_$(date +%Y%m%d_%H%M%S).sql.gz
find backups/ -name "backup_*.sql.gz" -mtime +30 -delete
EOF
chmod +x backup.sh
Restore Backup
# From SQL file
docker compose exec -T tux-postgres psql -U tuxuser tuxdb < backup.sql
# From gzip
gunzip < backup.sql.gz | docker compose exec -T tux-postgres psql -U tuxuser tuxdb
Monitoring
Health Checks
# Check container health
docker compose ps
# View health status
docker inspect tux --format='{{.State.Health.Status}}'
# Check logs for errors
docker compose logs --tail=100 tux | grep ERROR
Resource Usage
# View resource usage
docker stats
# Specific container
docker stats tux
Troubleshooting
Services Won't Start
# Check for errors
docker compose logs
# Validate compose.yaml
docker compose config
# Check Docker daemon
systemctl status docker # Linux
Database Connection Failed
# Check postgres is healthy
docker compose ps tux-postgres
# Check logs
docker compose logs tux-postgres
# Verify environment variables
docker compose exec tux env | grep POSTGRES
Permission Errors
# Check file permissions
ls -la .env config/
# Fix if needed
chmod 600 .env
chmod -R 644 config/
Port Conflicts
# Check what's using port
sudo lsof -i :5432 # PostgreSQL
sudo lsof -i :8080 # Adminer
# Change ports in .env
POSTGRES_PORT=5433
ADMINER_PORT=8081
Advanced Topics
Custom Image
Build from specific tag:
git checkout v1.0.0
docker compose build
docker compose up -d
Network Configuration
Containers communicate via Docker network:
- Network name:
tux_default
- Internal DNS: Container names resolve
- Isolation: Not accessible from host except exposed ports
Volumes Management
# List volumes
docker volume ls
# Inspect volume
docker volume inspect tux_postgres_data
# Backup volume
docker run --rm -v tux_postgres_data:/data -v $(pwd):/backup \
alpine tar czf /backup/postgres_backup.tar.gz /data
# Restore volume
docker run --rm -v tux_postgres_data:/data -v $(pwd):/backup \
alpine tar xzf /backup/postgres_backup.tar.gz -C /
Migration from Other Deployments
From VPS to Docker
- Backup current database
- Clone repository
- Set up
.env
with same settings - Start Docker Compose
- Restore database backup
- Stop old deployment
From One Server to Another
- Backup database and config
- Set up new server with Docker Compose
- Copy
.env
andconfig/
- Restore database
- Start services
Performance Tuning
PostgreSQL Configuration
Custom postgresql.conf
included at docker/postgres/postgresql.conf
.
Key settings:
shared_buffers
- Memory for cachingwork_mem
- Memory per operationmax_connections
- Connection limit
Bot Performance
Environment variables:
# In .env
POSTGRES_MAX_CONNECTIONS=20 # Connection pool size
Security
Production Checklist
- [ ] Change default database password
- [ ] Disable Adminer auto-login
- [ ] Don't expose PostgreSQL port publicly
- [ ] Use strong
.env
permissions (600) - [ ] Enable firewall (UFW or similar)
- [ ] Set up log monitoring
- [ ] Configure backup automation
- [ ] Use HTTPS for Adminer (reverse proxy)
Firewall
# Allow only necessary ports
sudo ufw allow 8080/tcp comment 'Adminer (dev only)'
# Don't allow 5432 publicly!
Useful Commands Reference
# Lifecycle
docker compose up -d # Start
docker compose down # Stop
docker compose restart # Restart
docker compose stop tux # Stop specific service
# Logs
docker compose logs -f # Follow all logs
docker compose logs -f tux # Follow bot logs
docker compose logs --tail=100 tux # Last 100 lines
# Updates
git pull # Get latest code
docker compose pull # Pull latest images
docker compose up -d --build # Rebuild and restart
# Database
docker compose exec tux uv run db push # Migrations
docker compose exec tux uv run db health # Health check
docker compose exec tux-postgres psql -U tuxuser tuxdb # psql shell
# Debugging
docker compose exec tux /bin/bash # Shell in container
docker compose ps # Service status
docker stats # Resource usage
Next Steps
After deployment:
- Configure Bot - Set up features and settings
- Run Migrations - Ensure database is up to date
- Set Up Monitoring - Watch for issues
- Configure Backups - Protect your data
Getting Help
- Troubleshooting - Common issues
- Discord Support - Ask #self-hosting
- GitHub Issues - Report bugs
Next: Configure Your Instance or try VPS Deployment.