Install Chatwoot on Ubuntu 20.04
Get your own self‑hosted help desk up and running without a single Docker nightmare.
Quick rundown
If you’re looking to run Chatwoot on a fresh 20.04 machine, this guide walks through the bare‑bones native installation: get Ruby, Node, PostgreSQL, Redis, clone the repo, configure your database, and launch the Rails server. No containers, no external services—just a straightforward setup that works in most home or small‑office environments.
Update the system and pull the essentials
sudo apt update && sudo apt upgrade -y sudo apt install -y git curl gnupg build-essential libpq-dev libssl-dev
Why it matters:
build-essential gives you a compiler toolchain for building native gems. libpq-dev is required for the PostgreSQL adapter; without it Rails will complain about missing symbols.
Install Node.js (Chatwoot’s asset pipeline needs it)
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt install -y nodejs
Why it matters:
Chatwoot uses Webpacker to bundle front‑end assets. The project currently supports Node 14+; the 16.x LTS is a safe bet and matches most Rails setups.
Add Yarn for JavaScript dependencies
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt update && sudo apt install -y yarn
Why it matters:
Yarn installs the JavaScript packages declared in package.json. You’ll see a cascade of warnings if you skip this step.
Pull Redis – Chatwoot’s pub/sub backbone
sudo apt install -y redis-server sudo systemctl enable --now redis.service
Why it matters:
Redis is used for broadcasting messages between agents and customers. If you forget to start it, the UI will silently freeze when you try to send or receive a chat.
Set up PostgreSQL
sudo apt install -y postgresql postgresql-contrib libpq-dev sudo -u postgres psql <<EOF CREATE USER chatwoot WITH PASSWORD 'chatwoot'; CREATE DATABASE chatwoot OWNER chatwoot; EOF
Why it matters:
Chatwoot stores all conversation history in PostgreSQL. The user and database names must match the DATABASE_URL we’ll set later. I’ve seen people mistakenly use the default postgres role, which leads to a 500 error page as soon as they hit the login screen.
Install Ruby (Chatwoot is a Rails app)
sudo apt install -y ruby-full ruby -v # should show 2.7+ or newer
Why it matters:
Rails 6 runs cleanly on Ruby 2.7+. If you try an older Ruby, you’ll hit syntax errors during bundle install.
Get the code
git clone https://github.com/chatwoot/chatwoot.git cd chatwoot # Optional: pin to a stable release tag git checkout v3.13.0 # replace with the latest LTS
Why it matters:
Using a tagged release keeps you from pulling in bleeding‑edge changes that might break your environment.
Install Ruby gems
# Tell bundler to skip dev/test groups on production install bundle config set --local without 'development test' bundle install
Why it matters:
Skipping those groups saves disk space and avoids installing unnecessary testing libraries. I once had a build fail because the sqlite3 gem was pulled in by mistake.
Install JavaScript packages
yarn install --frozen-lockfile
Why it matters:
Using the lockfile guarantees you get exactly what the repo expects, preventing version drift that could break your assets.
Pre‑compile assets
rails assets:precompile RAILS_ENV=production
Why it matters:
Chatwoot’s frontend is pre‑compiled for faster load times. Without this step you’ll see a blank page until the first user hits the “New chat” button.
Configure environment variables
cp .env.example .env # Edit .env with your editor, setting: DATABASE_URL=postgres://chatwoot:chatwoot@localhost/chatwoot REDIS_HOST=127.0.0.1 REDIS_PORT=6379 RAILS_MASTER_KEY= # if you have encrypted credentials
Why it matters:
The .env file feeds Rails at runtime. A typo in DATABASE_URL will cause a connection error that looks like “unrecognized host”.
Create database, run migrations and seed data
bundle exec rails db:create bundle exec rails db:migrate bundle exec rails db:seed
Why it matters:
db:seed populates the initial admin account. Without it you’ll have to hit a hidden route just to log in.
Start the server
# For development rails s -e production # Or create a systemd service for production use sudo tee /etc/systemd/system/chatwoot.service > /dev/null <<EOF [Unit] Description=Chatwoot Rails app After=network.target postgresql.service redis-server.service [Service] Type=simple User=www-data WorkingDirectory=/home/youruser/chatwoot ExecStart=/usr/bin/bundle exec rails s -e production Restart=on-failure [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now chatwoot.service
Why it matters:
Running Rails in production mode with systemd ensures it restarts automatically if something goes sideways. I’ve seen a few folks forget to set the working directory, which leads to “Missing database.yml” errors.
Point your browser
Navigate to http://your_server_ip:3000. Log in with the default credentials (admin@example.com / password). From there you can create real agents and start chatting.
Gotchas I’ve seen
- PostgreSQL version mismatch – After upgrading from 12 to 13, some people got “undefined method pg_connect”. Adding libpq-dev before the upgrade fixes it.
- Redis not listening on port 6379 – The default config disables IPv6 binding. Change bind 127.0.0.1 ::1 to just bind 127.0.0.1.
- Bundler errors during bundle install – Running bundle update --bundled-with before the first installation clears up a lot of “could not find gem” glitches.
Happy chatting! If something still feels off, drop a comment or ping the Chatwoot community; they’re surprisingly friendly for a dev‑heavy stack.