Install without Docker
Install Quackback without Docker using Bun and a direct PostgreSQL connection.
This guide is for users who prefer to run Quackback directly on their server without containerization.
Prerequisites
Bun
Version: 1.4.0 or higher
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Verify installation
bun --versionPostgreSQL
Version: 14 or higher
Required extensions:
vector(pgvector 0.5.0 or newer) for similarity searchpg_trgm(from the PostgreSQL contrib package) for text search
PostgreSQL is the only datastore you need. Background jobs, caches, and realtime events all run on it, so there is no Redis or queue service to install. See System Requirements for connection-mode and privilege requirements.
Other Tools
- Git
- OpenSSL (for generating secrets)
Installation Steps
1. Clone the Repository
git clone https://github.com/quackbackio/quackback.git
cd quackback2. Install Dependencies
bun install3. Configure Environment
Copy the example environment file:
cp .env.example .envGenerate a secure auth secret:
# Generate a 32-byte secret
openssl rand -base64 32Edit .env with your settings:
# Required settings
DATABASE_URL=postgresql://quackback:your_password@localhost:5432/quackback
SECRET_KEY=your-generated-secret-key-at-least-32-characters
BASE_URL=https://feedback.yourcompany.com
# One reverse proxy in front of the app (see the reverse proxy guide)
TRUSTED_PROXY_HOPS=1See Environment Variables for all options.
4. Set Up PostgreSQL
Install PostgreSQL 18
Ubuntu/Debian:
# Add PostgreSQL APT repository
sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
# Install PostgreSQL 18
sudo apt update
sudo apt install postgresql-18 postgresql-18-pgvectormacOS (Homebrew):
brew install postgresql@18
brew services start postgresql@18
# Install pgvector
brew install pgvectorRHEL/CentOS/Fedora:
# Install PostgreSQL 18 repo
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# Install PostgreSQL and extensions
sudo dnf install -y postgresql18-server postgresql18-contrib pgvector_18Create Database and User
# Switch to postgres user
sudo -u postgres psql-- Create user
CREATE USER quackback WITH PASSWORD 'your_secure_password';
-- Create database
CREATE DATABASE quackback OWNER quackback;
-- Connect to database
\c quackback
-- Enable required extensions (Quackback also tries this on startup)
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
-- Grant permissions
GRANT ALL PRIVILEGES ON DATABASE quackback TO quackback;
GRANT ALL ON SCHEMA public TO quackback;5. Run Migrations
bun run db:migrateThis creates all required tables and indexes. Before it changes anything, the migrator checks the PostgreSQL version, the extensions, and the database user's privileges, and stops with a clear message if something is missing.
6. Build the Application
bun run buildThis creates an optimized production build in apps/web/.output/.
7. Start the Server
bun run --cwd apps/web startThe server starts on port 3000 by default.
Process Management
For production, use a process manager to keep Quackback running and automatically restart on failures.
systemd (Recommended)
Create /etc/systemd/system/quackback.service:
[Unit]
Description=Quackback Feedback Platform
After=network.target postgresql.service
Requires=postgresql.service
[Service]
Type=simple
User=quackback
Group=quackback
WorkingDirectory=/opt/quackback
Environment=NODE_ENV=production
EnvironmentFile=/opt/quackback/.env
ExecStart=/home/quackback/.bun/bin/bun run --cwd apps/web start
Restart=always
RestartSec=10
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/quackback
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=quackback
[Install]
WantedBy=multi-user.targetEnable and start:
# Reload systemd
sudo systemctl daemon-reload
# Enable on boot
sudo systemctl enable quackback
# Start service
sudo systemctl start quackback
# Check status
sudo systemctl status quackback
# View logs
journalctl -u quackback -fOne instance handles everything by default (QUACKBACK_ROLE=all, the default when the variable is unset). To scale HTTP and background processing separately, add a second systemd unit with Environment=QUACKBACK_ROLE=worker (and set the first unit's QUACKBACK_ROLE=web). See Scale with multiple replicas.
PM2 (Alternative)
# Install PM2
bun install -g pm2
# Create ecosystem file
cat > ecosystem.config.js << 'EOF'
module.exports = {
apps: [{
name: 'quackback',
cwd: '/opt/quackback/apps/web',
script: '.output/server/index.mjs',
interpreter: 'bun',
env: {
NODE_ENV: 'production',
PORT: 3000
},
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G'
}]
}
EOF
# Start with PM2
pm2 start ecosystem.config.js
# Save configuration
pm2 save
# Enable startup script
pm2 startupDirectory Structure
Recommended production layout:
/opt/quackback/
├── .env # Environment configuration
├── apps/
│ └── web/
│ └── .output/ # Built application
├── packages/ # Internal packages
├── node_modules/ # Dependencies
├── package.json
└── bun.lock
Security Considerations
File Permissions
# Create dedicated user
sudo useradd -r -s /bin/false quackback
# Set ownership
sudo chown -R quackback:quackback /opt/quackback
# Restrict .env file
sudo chmod 600 /opt/quackback/.envFirewall
# UFW example
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP (for redirect)
sudo ufw allow 443/tcp # HTTPS
sudo ufw enableDo NOT expose port 3000 directly. Use a reverse proxy.
Update Quackback
Upgrading from 0.13? Read Upgrade from 0.13 to 0.14 first. It has one-time steps.
If you are using Docker, migrations run automatically on container startup. This manual migration step is only needed for non-Docker installations.
1. Stop the Service
sudo systemctl stop quackback2. Backup Database
pg_dump -Fc quackback > quackback_backup_$(date +%Y%m%d).dump3. Pull Updates
cd /opt/quackback
git pull origin main4. Install Dependencies
bun install5. Run Migrations
bun run db:migrate6. Rebuild
bun run build7. Restart Service
sudo systemctl start quackbackUpdate Script
Save this script as /opt/quackback/update.sh to automate the update process.
#!/bin/bash
set -e
cd /opt/quackback
echo "Stopping service..."
sudo systemctl stop quackback
echo "Creating backup..."
pg_dump -Fc quackback > /var/backups/quackback/quackback_$(date +%Y%m%d_%H%M%S).dump
echo "Pulling updates..."
git pull origin main
echo "Installing dependencies..."
bun install
echo "Running migrations..."
bun run db:migrate
echo "Building..."
bun run build
echo "Starting service..."
sudo systemctl start quackback
echo "Update complete!"Health Checks
Application Health
# Liveness: the process is up
curl http://localhost:3000/api/health/live
# Readiness: database, migrations, and background workers
curl http://localhost:3000/api/health/readyDatabase Connection
psql $DATABASE_URL -c "SELECT 1"Service Status
sudo systemctl status quackbackTroubleshooting
Port Already in Use
# Find what's using port 3000
sudo lsof -i :3000
# Kill the process or change PORT in .envDatabase Connection Failed
Check connection string format:
postgresql://user:password@host:port/database
Test connection:
psql "postgresql://quackback:password@localhost:5432/quackback" -c "SELECT 1"Permission Denied
Ensure the quackback user owns all files:
sudo chown -R quackback:quackback /opt/quackbackBuild Fails
Clear cache and reinstall:
rm -rf node_modules
rm -rf apps/web/.output
bun install
bun run buildMigrations Fail
Check database user permissions:
GRANT ALL PRIVILEGES ON DATABASE quackback TO quackback;
GRANT ALL ON SCHEMA public TO quackback;Next Steps
- Scale with multiple replicas - Split web and worker roles
- Reverse Proxy Configuration - Set up Nginx, Caddy, or Traefik
- Environment Variables - Configure email, OAuth, and integrations
- Troubleshooting - Common issues and solutions