Use case · Community forum

Self-hosted Discourse on a dedicated server

Self-hosted Discourse runs as one Docker container that the official installer builds for you: the Discourse team lists 1 GB of RAM (with swap), 1 core and 10 GB of disk as the minimum, and 2 GB+, 2+ cores and 20 GB+ as the recommendation, on 64-bit Linux, Ubuntu LTS preferred. It needs a domain name, ports 80 and 443 free, and either an SMTP provider or Discourse ID login. This page covers the figures, the install, the file that holds the secrets and the rebuild cycle.

See the machines

Discourse server requirements, as published

The official cloud install guide (INSTALL-cloud.md in the Discourse repository) publishes two columns. They are for the standard single-container install, where PostgreSQL, Redis and the Rails app share one container on one host.

ResourceMinimumRecommended
RAM1 GB (with swap)2 GB+
CPU1 core2+ cores
Disk10 GB20 GB+
OS64-bit LinuxUbuntu LTS

Two more numbers come from the tooling rather than the table. The installer sizes UNICORN_WORKERS (web workers) and db_shared_buffers from the RAM and CPU it detects, and the sample config says to keep db_shared_buffers at no more than 25% of memory. Before it builds, the launcher checks the disk that holds Docker's data directory (/var/lib/docker by default); with less than 5 GB free it offers to prune old Docker images and stops if that does not free enough. The guide gives no per-user or per-post figure, so size beyond the recommendation from your own traffic and upload volume, not from a rule of thumb.

Discourse will not run on a bare IP address. The hostname must be a real domain with an A record pointing at the server, or a free yoursite.discourse.diy subdomain claimed through Discourse ID during install.

Why a whole machine for one forum

No line on our dedicated server range has less than 8 GB of memory, four times the recommended 2 GB; the smallest cartridges start there and most lines start at 16 GB or more. That comparison is ours, not the guide's. The database, Redis and the web workers get every core with no neighbour on the box, and the installer tunes workers to what it finds.

  • Unmetered port. Image uploads, avatars and attachments are served from the same box. Ports marked Unmetered carry no transfer allowance and no overage fee.
  • Root and reinstalls. The OS can be reinstalled through the control panel whenever needed, which makes a clean retry of a failed bootstrap cheap.
  • Out-of-band console. Every racked single-, dual- and quad-socket server has HPE iLO, Dell iDRAC or a Supermicro BMC, so a firewall mistake on 22 does not lock you out. Among Moonshot cartridges only the m510 and m710x carry a console; the rest offer power control alone.
  • Delivery. A racked machine is handed over in about 30 minutes once payment is approved; a built-to-order line takes 4 to 24 hours.

For the class: the service page describes a Moonshot cartridge as one service per machine, which is exactly the standalone container, and a single-socket server as a web or application host with its database on the same box. NVMe storage helps PostgreSQL; the lines that carry it are on NVMe dedicated servers. Every x86 line runs a current Ubuntu LTS from the Linux images; the X-Gene ARM cartridge boots only Ubuntu 16.04 and 18.04, so leave it out for Discourse.

Install Discourse on Ubuntu

  1. Create an A record mapping the forum hostname, for example forum.example.com, to the machine's public IPv4. The installer checks that it resolves.
  2. Make sure nothing else holds ports 80 and 443: stop and disable any host nginx or Apache. The wizard validates both ports.
  3. Log in over SSH with root rights on a clean Ubuntu or Debian host and run the official one-liner below. It installs git and Docker if missing, clones discourse_docker to /var/discourse and starts the discourse-setup wizard.
  4. Answer the wizard: one or more admin emails (comma-separated), then either your own hostname or a free discourse.diy subdomain with the six-digit code from Discourse ID, then SMTP details or Skip.
  5. Confirm. The guide puts the build at about 5 to 10 minutes; Let's Encrypt certificates are provisioned without extra steps.
wget -qO- https://raw.githubusercontent.com/discourse/discourse_docker/main/install-discourse | sudo bash

Piping a script into a root shell runs whatever the URL serves. Fetch it to a file and read it first if your policy requires that; the script is short and sits in the public discourse_docker repository next to the launcher it calls.

app.yml: admin emails, SMTP and file mode

The wizard writes /var/discourse/containers/app.yml. Two blocks in it decide whether you ever reach the admin panel.

DISCOURSE_DEVELOPER_EMAILS is a comma-separated list. The sample template defines it as the emails that will be made admin and developer on initial signup. Nobody is admin by default: the first person to sign up with one of those addresses gets admin rights, and a stranger who reaches the site first gets an ordinary account. Register with an address on that list.

SMTP is optional since the current installer. Configure it and the signup for that admin address is confirmed by email, so the mail settings must actually deliver; the meta troubleshooting guide is blunt about it: with email broken you cannot log in as admin to finish the install, short of creating the account by hand inside the container (./launcher enter app, then rake admin:create), which it does not recommend. Skip it and the installer switches on login through Discourse ID at id.discourse.com, which also offers GitHub, Apple, Google and Facebook sign-in, and you lose digests, mailing list mode and reply by email until SMTP is added. The Docker image ships no mail server; the Discourse docs strongly recommend a dedicated email service and say to verify the forum's subdomain with it, not just the parent domain.

# excerpt of containers/app.yml (env section)
  DISCOURSE_DEVELOPER_EMAILS: 'admin@example.com'
  DISCOURSE_SMTP_ADDRESS: smtp.example.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: user@example.com
  DISCOURSE_SMTP_PASSWORD: "your-smtp-password"

# on the host, as root
cd /var/discourse
chmod 600 containers/app.yml

The SMTP password sits in that file in plain text; keep it in double quotes, because a # in an unquoted value is read as a comment. The launcher warns when app.yml is world-readable and suggests chmod o-rwx; chmod 600 goes further and still works as long as you run the launcher as root, as the install guide does; a non-root user would get a 'not readable' error. Keep the file out of any repository. Every edit to app.yml takes effect only after ./launcher rebuild app, which takes the forum offline while it builds (see below). If mail still fails, the ./discourse-doctor script in /var/discourse checks the mail configuration and suggests fixes.

Ports and exposure

The standalone template publishes exactly two ports, 80:80 and 443:443. PostgreSQL and Redis live inside the container and are not published. Docker opens those two ports itself, and Docker's own documentation warns that published ports bypass ufw rules; that is fine here because the forum must be public on both. Restrict SSH on the host as usual. The discourse_docker README adds one warning for multi-container setups: once the database runs in its own container, firewall the PostgreSQL and Redis ports.

Upgrades, rebuilds and logs

Discourse ships two upgrade paths. The guide recommends the web UI at /admin/upgrade. From the shell, ./launcher rebuild app stops the old container, bootstraps a new one from the current code, then removes the old one and starts the new one. Because the old container is stopped before the build begins, expect the forum to be offline while it builds (Discourse's email guide says a rebuild takes it offline for a few minutes). Before it builds, the rebuild also checks the discourse_docker checkout and pulls a newer launcher if there is one.

cd /var/discourse
./launcher rebuild app     # upgrade or apply app.yml changes
./launcher logs app        # container output
./launcher enter app       # shell inside the container
tail shared/standalone/log/rails/production.log

The guide also recommends unattended security upgrades for the host (dpkg-reconfigure -plow unattended-upgrades) and fail2ban. Discourse emails the admins when a new version is out.

Backups off the box

The container is stateless: everything durable is under /var/discourse/shared/standalone on the host. Automatic backups default to every 7 days (backup_frequency, 1 for daily), keep the 5 most recent (maximum_backups) and include uploads by default. Locally they land in /var/discourse/shared/standalone/backups/default, on the forum's own disk, so a disk failure takes both.

Set backup_location to S3 with a bucket used only for backups (a dedicated prefix if the bucket holds other files), or copy the local directory to another host on a schedule. Restoring onto a fresh install is the test that proves a backup works.

Where this is the wrong fit

The standalone install trades simplicity for downtime on every rebuild. If upgrades must not take the forum offline, the README's multi-container layout (separate data and web containers) lets a new web container bootstrap while the old one serves, at the cost of more setup. A trial forum for a handful of people fits inside the recommended 2 GB, and a Cloud VPS is a shared KVM guest sized for that; a whole machine earns its place once the forum carries real traffic and uploads. Pick the city nearest your members on the data center map.

Questions

How much RAM does a Discourse forum need?

The official install guide gives 1 GB with swap as the minimum and 2 GB or more as the recommendation, with 1 and 2+ CPU cores respectively. Those figures are for the standard single-container install. The installer then sizes web workers and PostgreSQL shared buffers from the memory and cores it finds, so more RAM is used rather than wasted.

Who becomes the first admin on a new Discourse install?

Whoever registers using one of the addresses in DISCOURSE_DEVELOPER_EMAILS in app.yml, which the wizard fills from the admin emails you type. Other visitors get normal accounts. If SMTP is configured, that signup is confirmed by email, so the mail settings have to work; the only way round it is creating the admin by hand with rake admin:create inside the container, which Discourse does not recommend.

Can Discourse run without an SMTP server?

Yes, with the current installer. Skip SMTP in the wizard and it turns on login through Discourse ID, with email-based and social sign-in handled at id.discourse.com. Digests, mailing list mode and replying by email need SMTP, which you can add later from the admin panel or by re-running the setup wizard.

Can another web server share ports 80 and 443 with Discourse?

Not in the default layout: the standalone container publishes 80 and 443 itself and the wizard checks that both are free. The sample app.yml points to a meta guide for running Discourse behind a separate nginx or Apache front end. On a dedicated machine, the simpler answer is to give Discourse the ports.

How do I upgrade a self-hosted Discourse?

Use the Upgrade button at /admin/upgrade, which the guide recommends, or run ./launcher rebuild app in /var/discourse. The rebuild replaces the container, so expect the forum to be offline while it builds. Take a backup first.

Does Discourse need Docker?

The supported install is Docker-based: the installer adds Docker if it is missing and the launcher manages the container. Discourse's own docs describe the standalone template as bundling everything Discourse needs into one container.

Put the forum on its own machine

Pick a line, install Ubuntu LTS, run the installer and register with your admin address.

See the machines

Related on Server Room

Other use cases