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 can be extended via plugins.
In this tutorial, you will learn how to install Discourse Forum with the Nginx server on a server running Rocky Linux 9.
Prerequisites
-
A server running Rocky Linux 9 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 dnf update
-
Few packages that your system needs.
$ sudo dnf install wget curl nano unzip yum-utils -y
Some of these packages may already be installed on your system.
Step 1 - Configure Firewall
The first step is to configure the firewall. Rocky Linux uses Firewalld Firewall. Check the firewall's status.
$ sudo firewall-cmd --state running
The firewall works with different zones, and the public zone is the default one that we will use. List all the services and ports active on the firewall.
$ sudo firewall-cmd --permanent --list-services
It should show the following output.
cockpit dhcpv6-client ssh
Discourse needs HTTP and HTTPS ports to function. Open them.
$ sudo firewall-cmd --permanent --add-service=http $ sudo firewall-cmd --permanent --add-service=https
Add masquerade, as the application will contact other instances.
$ sudo firewall-cmd --permanent --add-masquerade
Reload the firewall to apply the changes.
$ sudo firewall-cmd --reload
List all the services again.
$ sudo firewall-cmd --permanent --list-services
You should get the following output.
cockpit dhcpv6-client http https ssh
Configure SELinux
Discourse won't be accessible even if you open the ports due to SELinux's access policy. Configure SELinux to allow network connections.
$ sudo setsebool -P httpd_can_network_connect 1
Step 2 - Install Git
Install Git.
$ sudo dnf install git
Confirm the installation.
$ git --version git version 2.31.1
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
Rocky Linux ships with an older version of Docker. To install the latest version, first, install the official Docker repository.
$ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
Install the latest version of Docker.
$ sudo dnf install docker-ce docker-ce-cli containerd.io
You may get the following error while trying to install Docker.
ror: Problem: problem with installed package buildah-1:1.26.2-1.el9_0.x86_64 - package buildah-1:1.26.2-1.el9_0.x86_64 requires runc >= 1.0.0-26, but none of the providers can be installed - package containerd.io-1.6.9-3.1.el9.x86_64 conflicts with runc provided by runc-4:1.1.3-2.el9_0.x86_64 - package containerd.io-1.6.9-3.1.el9.x86_64 obsoletes runc provided by runc-4:1.1.3-2.el9_0.x86_64 - cannot install the best candidate for the job
Use the following command if you get the error above.
$ sudo dnf install docker-ce docker-ce-cli containerd.io --allowerasing
Enable and run the Docker daemon.
$ sudo systemctl enable docker --now
Verify that it is running.
? docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) Active: active (running) since Sat 2023-01-20 06:49:44 UTC; 6s ago TriggeredBy: ? docker.socket Docs: https://docs.docker.com Main PID: 99263 (dockerd) Tasks: 8 Memory: 28.1M CPU: 210ms CGroup: /system.slice/docker.service ??99263 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
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)
You will need to log out of the server and back in as the same user to enable this change or use the following command.
$ su - ${USER}
Confirm that your user is added to the Docker group.
$ groups navjot wheel docker
Step 4 - Download Discourse
Clone the official Discourse Docker GitHub repository to the /var/discourse
directory.
$ sudo git clone https://github.com/discourse/discourse_docker.git /var/discourse
Switch to the Discourse directory.
$ cd /var/discourse
Remove writing and executable permissions from the containers
directory.
$ sudo chmod 700 containers
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 Email IDs for the Administrator
Set the email for your administrator account and the developer using the variable DISCOURSE_DEVELOPER_EMAILS
. This step is compulsory otherwise, your forum won't be bootstrapped.
DISCOURSE_DEVELOPER_EMAILS: 'navjot@example.com,developer@example.com'
Configure SMTP Settings
Fill out the following variables depending on the transactional email service you are using.
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
Open port to test Discourse application.
$ sudo firewall-cmd --permanent --add-port=8080/tcp
You can now 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.
Step 7 - Install Nginx
Rocky Linux 9 ships with an older version of Nginx. You need to download the official Nginx repository to install the latest version.
Create and open the /etc/yum.repos.d/nginx.repo
file for creating the official Nginx repository.
$ sudo nano /etc/yum.repos.d/nginx.repo
Paste the following code in it.
[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true
Save the file by pressing Ctrl + X and entering Y when prompted.
Install the Nginx server.
$ sudo dnf install nginx
Verify the installation.
$ nginx -v nginx version: nginx/1.22.1
Enable and start the Nginx server.
$ sudo systemctl enable nginx --now
Check the status of the server.
$ sudo systemctl status nginx ? nginx.service - nginx - high performance web server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since Sun 2023-01-20 07:49:55 UTC; 1s ago Docs: http://nginx.org/en/docs/ Process: 230797 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS) Main PID: 230798 (nginx) Tasks: 3 (limit: 12355) Memory: 2.8M CPU: 13ms CGroup: /system.slice/nginx.service ??230798 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf" ??230799 "nginx: worker process" ??230800 "nginx: worker process"
Step 8 - 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 Rocky Linux doesn't ship with it, install the Snapd installer. It requires the EPEL repository to work.
$ sudo dnf install epel-release
Install Snapd.
$ sudo dnf install snapd
Enable and Start the Snap service.
$ sudo systemctl enable snapd --now
Install the Snap core package, and ensure that your version of Snapd is up to date.
$ sudo snap install core && sudo snap refresh core
Create necessary links for Snapd to work.
$ sudo ln -s /var/lib/snapd/snap /snap $ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh
Issue the following command to 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.32.2
Generate the SSL certificate.
$ sudo certbot certonly --nginx --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 -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
To check whether the SSL renewal is working fine, do a dry run of the process.
$ sudo certbot renew --dry-run
If you see no errors, you are all set. Your certificate will renew automatically.
Step 9 - Configure Nginx
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; location / { 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:SSL: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; http2_push_preload on; # Enable HTTP/2 Server Push # Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to # prevent replay attacks. # # @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data ssl_early_data on; # Security / XSS Mitigation Headers # NOTE: X-Frame-Options may cause issues with the webOS app add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; add_header X-Early-Data $tls1_3_early_data; 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; } } # This block is useful for debugging TLS v1.3. Please feel free to remove this # and use the `$ssl_early_data` variable exposed by NGINX directly should you # wish to do so. map $ssl_early_data $tls1_3_early_data { "~." $ssl_early_data; default ""; }
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
Restart the Nginx service to enable the new configuration.
$ sudo systemctl restart nginx
Step 10 - Access and Finish Discourse Install
You can access the forum by visiting the URL https://discourse.example.com
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. Fill in your forum name, and description, and choose the language. Click the Next button to proceed.
Next, you will be taken to the Member Experience page. Choose the options according to your requirement and click the Next button to proceed.
Next, you will be taken to the setup completion page. You can either choose to configure more or just Jump in and start using the forum. These settings can still be configured using the administrator settings.
We will choose Configure more for our tutorial. You will be taken to the page and asked to set logos and banner for your forum. Click the Next button to proceed.
Next, you will be asked to set basic styling options for the forum's front end. Click the Next button to proceed.
Next, you will be taken to the Organization configuration page. Fill in the appropriate information.
Click the Jump in! button to proceed. You will be taken to the forum home. Your Discourse forum is ready for use.
Step 11 - Discourse Commands
Activate Discourse Administrator from the command-line
If you don't receive the activation e-mail, 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:0x00007fdf020229f0 id: 1, username: "username", created_at: Fri, 20 Jan 2023 08:14:36.735552000 UTC +00:00, updated_at: Fri, 20 Jan 2023 14:14:12.094234000 UTC +00:00, name: nil, seen_notification_id: 4, last_posted_at: nil, password_hash: "98c774785bda45b4edbaea90eeb3bd5da00f65487ba6d0b3930082ce098bf174", salt: "ca175ea7f5653ce8122b76b68b549936", active: true, username_lower: "username", last_seen_at: Fri, 20 Jan 2023 23:01:21.001705000 UTC +00:00, admin: true, last_emailed_at: Fri, 20 Jan 2023 09:48:47.896200000 UTC +00:00, trust_level: 1, approved: false, approved_by_id: nil, approved_at: nil, previous_visit_at: Fri, 20 Jan 2023 21:28:23.665502000 UTC +00:00, suspended_at: nil, suspended_till: nil, date_of_birth: nil, views: 0, flag_level: 0, ip_address: #<IPAddr: IPv4:122.161.92.70/255.255.255.255>, moderator: false, title: nil, uploaded_avatar_id: nil, :
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.
Backup Discourse
Discourse backups the database every 7 days by default. You can find the backup files at the `/var/discourse/shared/standalone/backups/default
directory.
$ ls /var/discourse/shared/standalone/backups/default -al total 1480 drwxr-xr-x. 2 navjot tape 4096 Jan 21 03:34 . drwxr-xr-x. 3 navjot tape 4096 Jan 20 12:01 .. -rw-r--r--. 1 navjot tape 1503748 Jan 21 03:34 howtoforge-forums-2023-01-21-033439-v20230119094939.tar.gz
You can configure backup settings by visiting the Admin >> Settings >> Backups section. Discourse gives you the option to store the backups locally or to an Amazon S3-style cloud storage.
You can download the backups from the Admin >> Backups page. Restore is disabled by default. If you want to restore the database, you need to enable the allow restore option from Admin >> Settings >> Backups section.
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 app
View Discourse Logs
$ sudo ./launcher logs app
You can also view the detailed labs by visiting the URL https://discourse.example.com/logs/
in your browser. You will get a similar screen.
Rails / Unicorn Logs
Ruby on Rails contains a very verbose log that is written to disk. Additionally, the web server unicorn also logs to disk. You can view them at the var/discourse/shared/standalone/log/rails
directory.
$ ls /var/discourse/shared/standalone/log/rails -al total 552 drwxr-xr-x. 2 navjot tape 4096 Jan 20 07:09 . drwxr-xr-x. 4 root root 4096 Jan 20 07:09 .. -rw-r--r--. 1 navjot tape 0 Jan 20 07:09 production_errors.log -rw-r--r--. 1 navjot tape 361031 Jan 21 11:46 production.log -rw-r--r--. 1 navjot tape 0 Jan 20 07:09 sidekiq.log -rw-r--r--. 1 navjot tape 60919 Jan 20 08:42 unicorn.stderr.log -rw-r--r--. 1 navjot tape 119403 Jan 21 03:34 unicorn.stdout.log
Nginx Logs
Discourse runs an Nginx server inside a docker container. You can view the logs at the following location.
$ ls /var/discourse/shared/standalone/log/var-log/nginx -al total 1852 drwxr-xr-x. 2 33 tape 4096 Jan 20 07:39 . drwxrwxr-x. 5 root adm 4096 Jan 21 08:04 .. -rw-r--r--. 1 33 tape 1878744 Jan 21 12:18 access.log -rw-r--r--. 1 33 tape 1017 Jan 20 07:45 error.log
Redis Logs
You can get logs for the Redis database server at the following location. The most recent log entries will be in the current
file.
$ ls /var/discourse/shared/standalone/log/var-log/redis -al total 140 drwxr-xr-x. 2 root root 4096 Jan 20 07:39 . drwxrwxr-x. 5 root adm 4096 Jan 21 08:04 .. -rw-r--r--. 1 root root 127002 Jan 21 12:17 current -rw-------. 1 root root 0 Jan 20 07:39 lock
PostgreSQL Logs
You can view the PostgreSQL database logs at the following location.
ls /var/discourse/shared/standalone/log/var-log/postgres -al total 20 drwxr-xr-x. 2 root root 4096 Jan 20 07:39 . drwxrwxr-x. 5 root adm 4096 Jan 21 08:04 .. -rw-r--r--. 1 root root 11400 Jan 21 03:34 current -rw-------. 1 root root 0 Jan 20 07:39 lock
The most recent entries are in the current
file in that directory.
The remaining can be found in the /var/discourse/shared/standalone/log/var-log
itself.
ls /var/discourse/shared/standalone/log/var-log -al total 100 drwxrwxr-x. 5 root adm 4096 Jan 21 08:04 . drwxr-xr-x. 4 root root 4096 Jan 20 07:09 .. -rw-r--r--. 1 root adm 40943 Jan 21 12:17 auth.log -rw-r--r--. 1 root adm 0 Jan 20 08:41 kern.log -rw-r-----. 1 root adm 750 Jan 21 08:04 messages drwxr-xr-x. 2 33 tape 4096 Jan 20 07:39 nginx drwxr-xr-x. 2 root root 4096 Jan 20 07:39 postgres drwxr-xr-x. 2 root root 4096 Jan 20 07:39 redis -rw-r--r--. 1 root adm 23041 Jan 21 12:17 syslog -rw-r-----. 1 root adm 70 Jan 21 08:04 user.log
Conclusion
This concludes the tutorial. You have installed the Discourse forum using Docker behind the Nginx proxy web server on a Rocky Linux 9 server. If you have any questions, post them in the comments below.