I have Campfire running on my VPS. I added a new web service on that same VPS using Dokku. After that, Campfire would no longer start.
Once wants an exclusive relationship with my VPS. I want to leverage the VPS I'm already running - it has plenty of processing power for my multi-service use case.
It took some Internet sleuthing, some LLM help, and lots of trial and error, but I finally got it working. The rest of this post documents the steps that worked.
NOTE: I'm pretty new to Dokku and kind of stumbled into this solution. I'm writing it down for future me to reference if I need. If there are better ways to do any of the steps below I'd love to know!
The Problem & Solution
The once CLI expects to bind directly to ports 80 and 443, but Dokku's nginx reverse proxy is already using those ports.
The solution? Deploy Campfire as a regular Dokku app and let Dokku's nginx handle the proxying.
Step 1: Create the Dokku app
# Create the Dokku app
dokku apps:create campfire
# Mount your existing data volume (if you have Campfire data from a previous installation)
dokku storage:mount campfire /var/lib/docker/volumes/campfire-data/_data:/rails/storage
# Set required environment variables (use your Once token as the SECRET_KEY_BASE)
# Replace your-once-token-here with the token you received when purchasing Campfire
dokku config:set campfire SECRET_KEY_BASE="your-once-token-here"
# Deploy the Campfire Docker image
dokku git:from-image campfire registry.once.com/campfire:latest
# Set your domain
dokku domains:set campfire chat.yourdomain.com
# Enable SSL with Let's Encrypt
dokku letsencrypt:enable campfire
Step 2: Fix the Nginx Port Mapping
Here's where it gets tricky. The Campfire container has an internal reverse proxy (Thruster) on port 80 that forwards to Puma on port 3000. But Dokku's nginx config generator gets confused by the container's exposed ports and tries to proxy to port 443 (where nothing is listening).
We need to fix the nginx config to proxy to port 80 instead of 443.
Create the Fix Script
cat > /usr/local/bin/fix-campfire-nginx << 'EOF'
#!/bin/bash
sed -i 's/proxy_pass http:\/\/campfire-443;/proxy_pass http:\/\/campfire-80;/' /home/dokku/campfire/nginx.conf
nginx -t && systemctl reload nginx
EOF
chmod +x /usr/local/bin/fix-campfire-nginx
Run it Now
fix-campfire-nginx
Your Campfire should now be working at https://chat.yourdomain.com!
Step 3: Automate the Fix with a Dokku Plugin
To make sure the nginx config gets fixed automatically on every deploy, we'll create a custom Dokku plugin:
# Create the plugin directory
mkdir -p /var/lib/dokku/plugins/available/zzz-campfire-fix
# Create the plugin metadata
cat > /var/lib/dokku/plugins/available/zzz-campfire-fix/plugin.toml << 'EOF'
[plugin]
description = "Fix campfire nginx proxy configuration"
version = "0.1.0"
[plugin.config]
EOF
# Create the proxy-build-config hook
cat > /var/lib/dokku/plugins/available/zzz-campfire-fix/proxy-build-config << 'EOF'
#!/usr/bin/env bash
set -eo pipefail
APP="$1"
if [[ "$APP" == "campfire" ]] && [[ -f /home/dokku/campfire/nginx.conf ]]; then
echo "-----> Fixing campfire nginx config..."
sed -i 's/proxy_pass http:\/\/campfire-443;/proxy_pass http:\/\/campfire-80;/' /home/dokku/campfire/nginx.conf 2>/dev/null || true
sudo nginx -t && sudo systemctl reload nginx
echo "-----> Campfire nginx config fixed and reloaded"
fi
EOF
# Make it executable
chmod +x /var/lib/dokku/plugins/available/zzz-campfire-fix/proxy-build-config
# Create the core-post-deploy hook
cat > /var/lib/dokku/plugins/available/zzz-campfire-fix/core-post-deploy << 'EOF'
#!/usr/bin/env bash
set -eo pipefail
APP="$1"
if [[ "$APP" == "campfire" ]]; then
echo "-----> Fixing campfire nginx config..."
sed -i 's/proxy_pass http:\/\/campfire-443;/proxy_pass http:\/\/campfire-80;/' /home/dokku/campfire/nginx.conf 2>/dev/null || true
sudo nginx -t && sudo systemctl reload nginx
echo "-----> Campfire nginx config fixed and reloaded"
fi
EOF
chmod +x /var/lib/dokku/plugins/available/zzz-campfire-fix/core-post-deploy
# Enable the plugin
dokku plugin:enable zzz-campfire-fix
Note: The plugin is named
zzz-campfire-fix(with "zzz-" prefix) to ensure it loads alphabetically after the nginx-vhosts plugin, so our fix runs after the config is generated. It's, uhh, hacky, but it works! 🙃
Step 4: Test the Automation
Verify the plugin works by rebuilding:
dokku ps:rebuild campfire
You should see "Fixing campfire nginx config..." in the output, and your site should continue working after the rebuild.
Understanding Why This Works
The Campfire Docker image has:
- Thruster (a Rails reverse proxy) listening on port 80
- Puma (the Rails web server) listening on port 3000
Thruster internally forwards requests from port 80 to Puma on port 3000. So by configuring Dokku's nginx to proxy to the container's port 80, we let Thruster handle the internal routing to Puma.
Setting Up Automatic Updates
By default, the once CLI handles automatic updates for Campfire. However, since we're now managing deployment through Dokku, we need to set up our own update mechanism.
Step 1: Disable Once Auto-Updates
once auto-update off
Step 2: Create the Auto-Update Script
cat > /usr/local/bin/campfire-auto-update << 'EOF'
#!/bin/bash
set -e
LOG_FILE="/var/log/campfire-auto-update.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "Checking for Campfire updates..."
# Capture the once update output
UPDATE_OUTPUT=$(once update 2>&1)
log "$UPDATE_OUTPUT"
# Check if an update was applied (look for success indicators)
if echo "$UPDATE_OUTPUT" | grep -q "Already up-to-date"; then
log "No updates available. Campfire is already on the latest version."
exit 0
elif echo "$UPDATE_OUTPUT" | grep -qE "(updated|Update complete|new version|Successfully updated)"; then
log "Update detected! Redeploying Campfire via Dokku..."
dokku ps:rebuild campfire >> "$LOG_FILE" 2>&1
log "Campfire successfully redeployed with new version."
else
log "Update check completed but status unclear. Manual review recommended."
log "Full output: $UPDATE_OUTPUT"
fi
EOF
chmod +x /usr/local/bin/campfire-auto-update
Step 3: Test the Script
/usr/local/bin/campfire-auto-update
You should see output indicating whether an update is available.
Step 4: Set Up Daily Automatic Updates
Add a cron job to check for updates daily at 3 AM:
(crontab -l 2>/dev/null; echo "0 3 * * * /usr/local/bin/campfire-auto-update") | crontab -
Verify the cron job was added:
crontab -l | grep campfire
Monitoring Updates
Check the update logs anytime:
tail -f /var/log/campfire-auto-update.log
Or manually trigger an update check:
/usr/local/bin/campfire-auto-update
Managing Your Campfire Instance
Now that Campfire runs under Dokku, use these commands to manage it:
# View logs
dokku logs campfire -t
# Restart the app
dokku ps:restart campfire
# Rebuild the app
dokku ps:rebuild campfire
# Check status
dokku ps:report campfire
# View configuration
dokku config:show campfire
The once CLI won't work for starting/stopping anymore, but you have full control through Dokku.
Now I have Campfire happily running on the same VPS as my other projects, all managed through Dokku! 🔥
Or from the RSS feed
Hopefully you found this post helpful, if you have any questions or comments you can reach me via electronic mail.