Deploy Tux on a VPS using systemd for process management.
Advanced
This guide assumes Linux system administration experience. For easier deployment, see Docker Compose.
Overview
This deployment method:
- Runs Tux directly on the host (no containers)
- Uses systemd for process management
- Requires manual PostgreSQL setup
- Gives full control over the environment
Prerequisites
- Linux VPS (Ubuntu 22.04+, Debian 12+, or similar)
- Root or sudo access
- Python 3.13+
- PostgreSQL 15+
- 2GB+ RAM recommended
- SSH access
Installation Steps
1. System Update
sudo apt update && sudo apt upgrade -y
2. Install Dependencies
# Install required packages
sudo apt install -y python3 python3-pip python3-venv postgresql postgresql-contrib git curl
# Install UV (Python package manager)
curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.bashrc
3. Set Up PostgreSQL
# Create database and user
sudo -u postgres createdb tuxdb
sudo -u postgres createuser tuxuser
# Set password and grant permissions
sudo -u postgres psql << EOF
ALTER USER tuxuser WITH PASSWORD 'your_secure_password_here';
GRANT ALL PRIVILEGES ON DATABASE tuxdb TO tuxuser;
ALTER DATABASE tuxdb OWNER TO tuxuser;
EOF
4. Create Service User
# Create dedicated user for running Tux
sudo useradd -r -m -s /bin/bash tux
sudo -u tux -i
5. Clone and Install Tux
# As tux user
cd ~
git clone https://github.com/allthingslinux/tux.git
cd tux
# Install dependencies
uv sync
6. Configure Environment
# Create .env file
cat > .env << 'EOF'
BOT_TOKEN=your_discord_bot_token
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=tuxdb
POSTGRES_USER=tuxuser
POSTGRES_PASSWORD=your_secure_password
ENVIRONMENT=production
DEBUG=false
EOF
# Secure permissions
chmod 600 .env
7. Run Migrations
uv run db push
8. Test Bot
# Test run
uv run tux start
# Should connect to Discord
# Press Ctrl+C to stop
9. Create Systemd Service
Exit the tux user shell and create service file:
# As root/sudo
sudo nano /etc/systemd/system/tux.service
Service file content:
[Unit]
Description=Tux Discord Bot
After=network.target postgresql.service
Requires=postgresql.service
[Service]
Type=simple
User=tux
Group=tux
WorkingDirectory=/home/tux/tux
Environment=PATH=/home/tux/tux/.venv/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/home/tux/tux/.venv/bin/python -m tux
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=tux
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/home/tux/tux/data /home/tux/tux/logs
ProtectKernelTunables=true
ProtectControlGroups=true
[Install]
WantedBy=multi-user.target
10. Enable and Start Service
# Reload systemd
sudo systemctl daemon-reload
# Enable service (start on boot)
sudo systemctl enable tux
# Start service
sudo systemctl start tux
# Check status
sudo systemctl status tux
Management Commands
Service Control
# Start
sudo systemctl start tux
# Stop
sudo systemctl stop tux
# Restart
sudo systemctl restart tux
# Status
sudo systemctl status tux
# Enable (start on boot)
sudo systemctl enable tux
# Disable (don't start on boot)
sudo systemctl disable tux
Logs
# View recent logs
sudo journalctl -u tux -n 100
# Follow logs
sudo journalctl -u tux -f
# Logs since boot
sudo journalctl -u tux -b
# Logs from last hour
sudo journalctl -u tux --since "1 hour ago"
# Search logs
sudo journalctl -u tux | grep ERROR
Database Operations
# As tux user
sudo -u tux -i
cd ~/tux
# Run migrations
uv run db push
# Check health
uv run db health
# Backup database
pg_dump -h localhost -U tuxuser tuxdb > backup_$(date +%Y%m%d).sql
Updating Tux
# As tux user
sudo -u tux -i
cd ~/tux
# Pull latest changes
git pull
# Update dependencies
uv sync
# Run new migrations
uv run db push
# Exit tux user
exit
# Restart service
sudo systemctl restart tux
# Check logs
sudo journalctl -u tux -f
Monitoring
Log Rotation
Create logrotate configuration:
sudo nano /etc/logrotate.d/tux
Content:
/home/tux/tux/logs/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 tux tux
postrotate
systemctl reload tux > /dev/null 2>&1 || true
endscript
}
Health Monitoring
Create health check script:
sudo nano /usr/local/bin/check-tux.sh
Content:
#!/bin/bash
if ! systemctl is-active --quiet tux; then
echo "Tux is down! Restarting..."
systemctl restart tux
# Optional: Send alert
# curl -X POST webhook_url -d "Tux restarted"
fi
Add to cron:
# Check every 5 minutes
*/5 * * * * /usr/local/bin/check-tux.sh
Security
Firewall
# Install UFW
sudo apt install ufw
# Allow SSH
sudo ufw allow ssh
# Allow PostgreSQL (only if needed externally)
# sudo ufw allow 5432/tcp
# Enable firewall
sudo ufw enable
PostgreSQL Security
# Edit PostgreSQL config
sudo nano /etc/postgresql/15/main/postgresql.conf
# Listen only on localhost
listen_addresses = 'localhost'
# Reload
sudo systemctl reload postgresql
Service Hardening
The provided systemd service includes security features:
NoNewPrivileges
- Prevent privilege escalationPrivateTmp
- Isolated /tmpProtectSystem
- Read-only system directoriesProtectHome
- Protected home directories
Troubleshooting
Service Won't Start
# Check status
sudo systemctl status tux
# Check logs
sudo journalctl -u tux -n 50
# Validate service file
systemd-analyze verify tux.service
# Test manually
sudo -u tux -i
cd ~/tux
uv run tux start
Permission Errors
# Fix ownership
sudo chown -R tux:tux /home/tux/tux
# Fix .env permissions
sudo -u tux chmod 600 /home/tux/tux/.env
Database Connection Issues
# Check PostgreSQL is running
sudo systemctl status postgresql
# Test connection
psql -h localhost -U tuxuser -d tuxdb
# Check pg_hba.conf
sudo nano /etc/postgresql/15/main/pg_hba.conf
Performance Tuning
PostgreSQL
Edit /etc/postgresql/15/main/postgresql.conf
:
shared_buffers = 256MB # 25% of RAM
effective_cache_size = 1GB # 50-75% of RAM
work_mem = 16MB
maintenance_work_mem = 128MB
max_connections = 100
Restart PostgreSQL:
sudo systemctl restart postgresql
System Resources
Monitor with:
htop # Interactive process viewer
free -h # Memory usage
df -h # Disk usage
Advantages & Disadvantages
✅ Advantages
- Maximum performance (no container overhead)
- Complete control
- Direct access to everything
- Easier debugging
- Lower resource usage
❌ Disadvantages
- More complex setup
- Manual dependency management
- Harder updates
- Requires Linux experience
- More maintenance
Next Steps
- Configure Tux - Set up features
- Set Up Backups - Protect your data
- Configure Monitoring - Watch for issues
- Security Hardening - Lock it down
Alternative: Try Docker Compose for easier management.