Deployment Guide
This guide covers deployment, maintenance, and operations for the Signal Bot using the deploy.sh script.
Prerequisites
Section titled “Prerequisites”- Docker and Docker Compose v2+
- SSH access to the production server
- A registered Signal phone number for the bot
deploy.sh Command Reference
Section titled “deploy.sh Command Reference”The deploy.sh script manages all deployment operations.
./deploy.sh [command] [options]Commands
Section titled “Commands”| Command | Description |
|---|---|
deploy | Full deployment: sync code + rebuild + restart (default) |
sync | Sync code, config, and memes without rebuilding |
rebuild | Rebuild container without syncing |
restart | Restart container without rebuilding |
logs [-t N] | Show last N log lines (default: 50) |
follow | Follow logs in real-time (Ctrl+C to stop) |
status | Show container status and startup logs |
shell | Open shell inside the container |
env | Show environment variables (masked) |
test-api | Test PeerTube and Local AI connectivity |
test-minio | Test MinIO S3 configuration |
test-shlink | Test Shlink URL shortener |
test-formatting | Test markdown-to-Signal formatting |
sync-db-memes | Download all database memes to storage |
cleanup [N] | Remove old Docker images (keep last N, default: 5) |
rebuild-signal-cli | Force rebuild signal-cli from master (fixes binary ACI encoding) |
help | Show usage information |
Options
Section titled “Options”| Option | Description |
|---|---|
-v, --verbose | Show verbose output |
-n, --no-cache | Force rebuild without Docker cache |
-t, --tail N | Number of log lines to show |
Examples
Section titled “Examples”# Standard deployment (sync + rebuild + restart)./deploy.sh
# Deploy with fresh build (no cache)./deploy.sh deploy --no-cache
# Only sync code without rebuilding./deploy.sh sync
# View last 100 log lines./deploy.sh logs -t 100
# Watch logs in real-time./deploy.sh follow
# Check container status./deploy.sh status
# Test integrations./deploy.sh test-minio./deploy.sh test-api
# Open shell for debugging./deploy.sh shell
# Clean up old images (keep last 3)./deploy.sh cleanup 3Deployment Workflow
Section titled “Deployment Workflow”Standard Code Update
Section titled “Standard Code Update”When making code changes:
# 1. Make changes locally in src/src/vim src/src/bot/command-handler.ts
# 2. Deploy with no-cache to ensure fresh build./deploy.sh deploy --no-cache
# 3. Verify the deployment./deploy.sh status./deploy.sh logs -t 50Quick Config Update
Section titled “Quick Config Update”For environment variable or config changes:
# 1. Edit local config filesvim compose.ymlvim .env.example # Copy to server manually
# 2. Sync config files./deploy.sh sync
# 3. Restart to apply./deploy.sh restartEmergency Restart
Section titled “Emergency Restart”If the bot stops responding:
./deploy.sh restart# or./deploy.sh deployServer Configuration
Section titled “Server Configuration”| Item | Value |
|---|---|
| Host | proxmox (Tailscale IP: 100.87.20.88) |
| Remote Path | /home/signal-bot-selfhosted/ |
| Container Name | signal-bot-selfhosted-signal-bot-1 |
| Compose Service | signal-bot |
Directory Structure
Section titled “Directory Structure”/home/signal-bot-selfhosted/├── .env # Environment variables (credentials)├── compose.yml # Docker Compose configuration├── Dockerfile.selfhosted # Docker build file├── src/ # Bot source code (synced)│ ├── src/ # TypeScript source│ ├── dist/ # Compiled JavaScript│ └── package.json├── signal-data/ # Signal CLI account data (CRITICAL!)├── data/│ ├── postgres/ # PostgreSQL data volume│ ├── redis/ # Redis data volume│ ├── memes/ # Persistent meme storage│ └── backups/ # Database backups├── database/ # SQL migration scripts│ ├── 000_base_schema.sql│ └── 001_*.sql ...└── memes/ # Local meme GIF filesWhat Gets Synced
Section titled “What Gets Synced”The deploy script syncs:
| Source | Destination | Notes |
|---|---|---|
./src/ | /home/signal-bot-selfhosted/src/ | Source code (excludes node_modules, .git) |
./compose.yml | /home/signal-bot-selfhosted/compose.yml | Creates backup first |
./Dockerfile.selfhosted | /home/signal-bot-selfhosted/Dockerfile.selfhosted | Build configuration |
./memes/ | /home/signal-bot-selfhosted/data/memes/ | Local meme files |
NOT synced (preserved on server):
.env- Contains credentialssignal-data/- Signal CLI registrationdata/postgres/- Database filesdata/redis/- Cache data
Docker Networks
Section titled “Docker Networks”The bot uses multiple Docker networks:
| Network | Purpose |
|---|---|
signal-bot-network | Internal bot communication |
minio-network | External: MinIO S3 access |
postgres-network | External: Shlink access |
Important: Use full container names (e.g., signal-bot-postgres) instead of short names to avoid DNS conflicts across networks.
Health Monitoring
Section titled “Health Monitoring”Built-in Health Endpoint
Section titled “Built-in Health Endpoint”curl http://localhost:8080/healthReturns:
{ "status": "ok", "timestamp": "2026-01-23T12:00:00.000Z", "uptime": 86400, "memory": { "rss": 150000000, "heapUsed": 80000000 }}Watchdog Features
Section titled “Watchdog Features”The bot includes automatic monitoring:
- Daemon health check: Every 60 seconds
- Auto-restart: On daemon death or disconnect
- Message flow monitoring: Alerts if no messages for 10+ minutes
- Restart notifications: Sends alerts to Bot Dev room
Manual Health Checks
Section titled “Manual Health Checks”# Check container status./deploy.sh status
# View health endpointssh proxmox "docker exec signal-bot-selfhosted-signal-bot-1 curl -s http://localhost:8080/health | jq"
# Check for errors in logs./deploy.sh logs -t 200 | grep -i errorBackup Procedures
Section titled “Backup Procedures”Signal Account Data (CRITICAL)
Section titled “Signal Account Data (CRITICAL)”The signal-data/ directory contains Signal CLI registration data. If lost, you must re-register the phone number.
# Backup signal-datassh proxmox "cd /home/signal-bot-selfhosted && tar -czf signal-data-backup-$(date +%Y%m%d).tar.gz signal-data/"
# Download to local machinescp proxmox:/home/signal-bot-selfhosted/signal-data-backup-*.tar.gz ./backups/Database Backup
Section titled “Database Backup”# Create backup on serverssh proxmox "docker exec signal-bot-postgres pg_dump -U signal_bot signal_bot > /home/signal-bot-selfhosted/data/backups/backup_$(date +%Y%m%d).sql"
# Compressed backupssh proxmox "docker exec signal-bot-postgres pg_dump -U signal_bot signal_bot | gzip > /home/signal-bot-selfhosted/data/backups/backup_$(date +%Y%m%d).sql.gz"Automated Backup Script
Section titled “Automated Backup Script”Create a cron job on the server:
# Edit crontabcrontab -e
# Add daily backup at 3 AM0 3 * * * docker exec signal-bot-postgres pg_dump -U signal_bot signal_bot | gzip > /home/signal-bot-selfhosted/data/backups/backup_$(date +\%Y\%m\%d).sql.gzRecovery Procedures
Section titled “Recovery Procedures”Restore from Database Backup
Section titled “Restore from Database Backup”# Stop the botdocker compose stop signal-bot
# Restore databasedocker exec -i signal-bot-postgres psql -U signal_bot signal_bot < backup.sql
# Start the botdocker compose start signal-botRestore Signal Registration
Section titled “Restore Signal Registration”# Stop the botdocker compose stop signal-bot
# Extract backupcd /home/signal-bot-selfhostedtar -xzf signal-data-backup-20260123.tar.gz
# Start the botdocker compose start signal-botFull Disaster Recovery
Section titled “Full Disaster Recovery”If the entire server is lost:
- Set up new server with Docker
- Clone repository and copy config
- Restore
signal-data/backup (or re-register) - Restore database backup
- Run
./deploy.sh deploy
Disk Space Management
Section titled “Disk Space Management”Check Docker Disk Usage
Section titled “Check Docker Disk Usage”ssh proxmox "docker system df"Clean Up Old Images
Section titled “Clean Up Old Images”# Keep last 5 images (default)./deploy.sh cleanup
# Keep last 3 images./deploy.sh cleanup 3This removes:
- Old signal-bot images
- Dangling images
- Build cache (keeps 2GB)
Troubleshooting Deployments
Section titled “Troubleshooting Deployments”Container Won’t Start
Section titled “Container Won’t Start”# Check logs for errors./deploy.sh logs -t 100
# Common issues:# - Missing environment variables# - Database connection failed# - Signal-CLI registration missingCode Changes Not Applied
Section titled “Code Changes Not Applied”# Force rebuild with no cache./deploy.sh deploy --no-cacheEnvironment Variables Missing
Section titled “Environment Variables Missing”# Check what's in the container./deploy.sh env
# Verify specific variablesssh proxmox "docker exec signal-bot-selfhosted-signal-bot-1 printenv | grep ADMIN"Security Considerations
Section titled “Security Considerations”Environment Variables
Section titled “Environment Variables”- Never commit
.envfiles to git - Use unique, strong passwords for database
- Rotate API tokens periodically
- Restrict admin UUIDs to trusted users
Container Security
Section titled “Container Security”- Container runs as
nodeuser (not root) - Network isolation via Docker networks
- Only necessary ports exposed
Signal Account Security
Section titled “Signal Account Security”- Keep
signal-data/backed up securely - Don’t share Signal registration data
- Use a dedicated phone number for the bot
Related Documentation
Section titled “Related Documentation”- Self-Hosting Guide - Initial setup
- Database Schema - Database setup and migrations
- Troubleshooting - Common issues
- Configuration Reference - Environment variables