Discourse is an open-source community discussion platform built using the Ruby language. It is designed to work as a forum, chat software or mailing list. It integrates easily with other platforms, and its functionality can be expanded with plugins.
In this tutorial, you will learn how to install Discourse Forum with the Nginx server on a Debian 11 based server.
Prerequisites
-
A server running Debian 11 with a minimum of 1GB RAM and 1 Core CPU. Discourse setup will automatically create a swap partition on systems with 1GB or less RAM. Therefore, it is recommended to install it on a system with at least 2GB RAM.
-
A non-root user with sudo privileges.
-
A Domain name (
discourse.example.com
) pointing to the server. -
Everything is updated.
$ sudo apt update && sudo apt upgrade
-
Few packages that your system needs.
$ sudo apt install nano ufw software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release debian-archive-keyring -y
Some of these packages may already be installed on your system.
Step 1 - Configure Firewall
The first step is to configure the firewall. Debian comes with ufw (Uncomplicated Firewall).
Check if the firewall is running.
$ sudo ufw status
You should get the following output.
Status: inactive
Allow SSH port so that the firewall doesn't break the current connection on enabling it.
$ sudo ufw allow OpenSSH
Allow HTTP and HTTPS ports as well.
$ sudo ufw allow 80/tcp $ sudo ufw allow 443/tcp
Enable the Firewall
$ sudo ufw enable Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startup
Check the status of the firewall again.
$ sudo ufw status
You should see a similar output.
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere 80/tcp ALLOW Anywhere 443/tcp ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) 80/tcp (v6) ALLOW Anywhere (v6) 443/tcp (v6) ALLOW Anywhere (v6)
Step 2 - Install Git
Install Git using the default Appstream.
$ sudo dnf install git
Confirm the installation.
$ git --version git version 2.30.2
Run the following commands to configure the Git installation.
$ git config --global user.name "Your Name" $ git config --global user.email "youremail@example.com"
Step 3 - Install Docker
To install the latest version of Docker, add Docker's official GPG key.
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
Install the official Docker repository.
$ echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Update Debian system repositories.
$ sudo apt update
Install the latest version of Docker.
$ sudo apt install docker-ce docker-ce-cli containerd.io
Verify that Docker is running.
$ sudo systemctl status docker ? docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2022-02-05 13:32:54 UTC; 1h ago TriggeredBy: ? docker.socket Docs: https://docs.docker.com Main PID: 5818 (dockerd) Tasks: 26 Memory: 1.4G CPU: 5min 34.561s CGroup: /system.slice/docker.service ?? 5818 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ??12162 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 172.17.0.2 -contai> ??12169 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 8080 -container-ip 172.17.0.2 -container-p>
By default, Docker requires root privileges. If you want to avoid using sudo
every time you run the docker
command, add your username to the docker
group.
$ sudo usermod -aG docker $(whoami)
To enable this change, you will need to log out of the server and back in as the same user.
Step 4 - Download Discourse
Create the root directory for Discourse.
$ sudo mkdir /var/discourse
Clone the official Discourse Docker Github repository.
$ sudo git clone https://github.com/discourse/discourse_docker.git /var/discourse
Step 5 - Configure Discourse
Create the configuration file app.yml
by copying the sample standalone.yml
file.
$ sudo cp samples/standalone.yml containers/app.yml
Open the app.yml
for editing.
$ sudo nano containers/app.yml
Set Domain
Set the variable DISCOURSE_HOSTNAME
to the domain name, you chose for your forum. If you don't have a domain name, you can use an IP address here.
DISCOURSE_HOSTNAME: 'discourse.example.com'
Configure Exposed ports
Change the line "80:80
to "8080:80"
. This will change the external HTTP port for Discourse to 8080 since we will use Nginx at port 80. Comment out the "443:443"
line since we will install SSL externally.
expose: - "8080:80" # http #- "443:443" # https
Configure SMTP Settings
Fill out the following variables depending upon the transactional email service you are using. Set the email for your administrator account using the variable DISCOURSE_DEVELOPER_EMAILS
. This step is compulsory otherwise, your forum won't be bootstrapped.
.. DISCOURSE_DEVELOPER_EMAILS: 'name@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 #DISCOURSE_SMTP_ENABLE_START_TLS: true # (optional, default true) #DISCOURSE_SMTP_DOMAIN: discourse.example.com # (required by some providers) DISCOURSE_NOTIFICATION_EMAIL: noreply@discourse.example.com # (address to send notifications from)
Memory Settings (Optional)
If your server has low RAM, you can configure the following variables accordingly to reduce Discourse's memory footprint.
db_shared_buffers: '128MB' UNICORN_WORKERS: 2
The variable db_shared_buffers
is usually set to 25% of the available memory.
GeoLite2 Settings (Optional)
If you want the IP lookup feature on Discourse, signup for the free Maxmind Geolite2 account and get a license key. Paste that license key as the value for the following variable.
DISCOURSE_MAXMIND_LICENSE_KEY: your_maxmind_license_key
Save the file by pressing Ctrl + X and entering Y when prompted.
Step 6 - Install Discourse
Run the following command to bootstrap your Discourse container.
$ sudo ./launcher bootstrap app
Start Discourse application.
$ sudo ./launcher start app
You can access the forum by visiting the URLs http://yourserver_IP:8080
or http://discourse.example.com:8080
in your browser. You will get the following screen.
Click the Register button to proceed. The email id set in the app.yml
file will be pre-filled for you.
Click the Register button to register the administrator account. You will proceed to the email confirmation screen.
If your SMTP settings are correct, you will receive a mail to activate the account. Click the link from your email to finish setting up the account.
Click the Activate button to finish the installation.
You will get to the Discourse's Setup Wizard screen. You can either skip it to proceed directly to the forum or go through the entire wizard.
Your Discourse forum is ready. The next step is installing SSL and putting the forum behind the Nginx server.
Step 7 - Install SSL
To install an SSL certificate using Let's Encrypt, we need to install the Certbot tool.
We will use the Snapd package installer for that. Since most Debian servers don't ship with it, install the Snapd installer.
$ sudo apt install snapd
Ensure that your version of Snapd is up to date.
$ sudo snap install core && sudo snap refresh core
Install Certbot.
$ sudo snap install --classic certbot
Use the following command to ensure that the Certbot command can be run by creating a symbolic link to the /usr/bin
directory.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Verify the installation.
$ certbot --version certbot 1.22.0
Generate the SSL certificate.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m name@example.com -d discourse.example.com
The above command will download a certificate to the /etc/letsencrypt/live/discourse.example.com
directory on your server.
Generate a Diffie-Hellman group certificate.
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Create a challenge webroot directory for Let's Encrypt auto-renewal.
$ sudo mkdir -p /var/lib/letsencrypt
Create a Cron Job to renew the SSL. It will run every day to check the certificate and renew if needed. For that, first, create the file /etc/cron.daily/certbot-renew
and open it for editing.
$ sudo nano /etc/cron.daily/certbot-renew
Paste the following code.
#!/bin/sh certbot renew --cert-name discourse.example.com --webroot -w /var/lib/letsencrypt/ --post-hook "systemctl reload nginx"
Save the file by pressing Ctrl + X and entering Y when prompted.
Change the permissions on the task file to make it executable.
$ sudo chmod +x /etc/cron.daily/certbot-renew
Step 8 - Install and Configure Nginx
Debian ships with an older version of Nginx. You need to download the official Nginx repository to install the latest version.
Import the official Nginx signing key.
$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
Add the repository for Nginx's stable version.
$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg arch=amd64] \ http://nginx.org/packages/debian `lsb_release -cs` nginx" \ | sudo tee /etc/apt/sources.list.d/nginx.list
Update the Debian repositories.
$ sudo apt update
Install Nginx.
$ sudo apt install nginx
Verify the installation. Make sure you use sudo
every time you run the Nginx command on Debian. Otherwise, it won't work.
$ sudo nginx -v nginx version: nginx/1.20.2
Create and open the file /etc/nginx/conf.d/discourse.conf
for editing.
$ sudo nano /etc/nginx/conf.d/discourse.conf
Paste the following code in it.
# enforce HTTPS server { listen 80; listen [::]:80; server_name discourse.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name discourse.example.com; access_log /var/log/nginx/discourse.access.log; error_log /var/log/nginx/discourse.error.log; # SSL ssl_certificate /etc/letsencrypt/live/discourse.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/discourse.example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/discourse.example.com/chain.pem; ssl_session_timeout 5m; ssl_session_cache shared:MozSSL:10m; ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; ssl_stapling on; ssl_stapling_verify on; ssl_dhparam /etc/ssl/certs/dhparam.pem; resolver 8.8.8.8; client_max_body_size 100m; location / { proxy_pass http://discourse.example.com:8080/; proxy_set_header Host $http_host; proxy_http_version 1.1; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; } }
Save the file by pressing Ctrl + X and entering Y when prompted once finished.
Open the file /etc/nginx/nginx.conf
for editing.
$ sudo nano /etc/nginx/nginx.conf
Add the following line before the line include /etc/nginx/conf.d/*.conf;
.
server_names_hash_bucket_size 64;
Save the file by pressing Ctrl + X and entering Y when prompted.
Verify the Nginx configuration file syntax.
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Start the Nginx service to enable the new configuration.
$ sudo systemctl start nginx
Step 9 - Discourse Commands
Activate Discourse Administrator from the command-line
If you don't receive the activation email, you can activate the administrator account from the command line.
Switch to the Discourse directory.
$ cd /var/discourse
Enter the Discourse container Shell.
$ sudo ./launcher enter app
Enter the command rails c
to access the Rails command prompt.
root@discourse-app:/var/www/discourse# rails c
You will see the following prompt.
[1] pry(main)>
Enter the command to locate the administrator account.
[1] pry(main)> User.find_by_email("name@example.com") => #<User:0x00005564492032a0 id: 1, username: "username", created_at: Sun, 06 Feb 2022 14:46:58.451302000 UTC +00:00, updated_at: Sun, 06 Feb 2022 14:54:17.079564000 UTC +00:00, name: nil, seen_notification_id: 4, last_posted_at: nil, password_hash: "[FILTERED]", salt: "20d6012d3c98da70896dcfc27bc9d264", active: true, username_lower: "username", last_seen_at: Mon, 07 Feb 2022 08:34:12.435844000 UTC +00:00, admin: true, last_emailed_at: Sun, 06 Feb 2022 14:47:00.694121000 UTC +00:00, trust_level: 1, approved: false, approved_by_id: nil, approved_at: nil, previous_visit_at: Sun, 06 Feb 2022 15:40:35.804941000 UTC +00:00, suspended_at: nil, suspended_till: nil, date_of_birth: nil, views: 0, flag_level: 0, ip_address: #<IPAddr: IPv4:69.28.90.35/255.255.255.255>, moderator: false, title: nil, uploaded_avatar_id: 3, :
Enter q
to return to the prompt and enter the following commands in sequence.
[2] pry(main)> user.approved = true [3] pry(main)> user.save [4] pry(main)> EmailToken.confirm(user.email_tokens.first.token)
Type exit
twice to return to the shell. Your administrator account is activated and ready for use.
Upgrade Discourse
To upgrade the forum, you can use one of two ways. The first way is to upgrade it via the administrator dashboard. The second method is to use a command line.
Switch to the Discourse directory.
$ cd /var/discourse
Update the Discourse installation by grabbing the latest files from Github.
$ git pull
Rebuild Discourse.
$ sudo ./launcher rebuild app
You need to rebuild Discourse every time you make any changes in the app.yml
file. After making the changes, run the command above. It destroys the old container, bootstraps a new one and starts it.
Stop Discourse
$ sudo ./launcher stop
View Discourse Logs
$ sudo ./launcher logs
Conclusion
This concludes the tutorial. You have installed the Discourse forum using Docker behind the Nginx web server on a Debian 11 server. If you have any questions, post them in the comments below.