Background
When setting up a new Discourse instance, there are a number of steps which should be followed to ensure a consistent, secure output. While it’s possible to fully automate a process like this using tools such as Ansible, the efficiency of scripting the process is only realised if you’re doing this very frequently, and also you need to be prepared to repair the script frequently when small details change.
Checklists
Another option, and the one I’ve chosen here, is the approach of creating a ‘checklist’ or ‘runbook’ which contains step-by-step commands to result in a consistent output. The other benefit of this compared to a script is that it also provides an opportunity for the sysadmin to make small adaptations on-the-fly, and to understand the process that has been gone through.
Placeholders
Place details here and the commands in the rest of the checklist will be auto-filled for you
Fully-qualified Domain name you wish to use for the Discourse server once set up
Name of the new non-root user you want to create on the server
The
ssh-import-id
SSH Key identity you want to use for the new non-root user (Optional)
(ssh-import-id
is able to pull SSH public keys from GitHub so a good way to do this is to upload an SSH public key to your GitHub account and use the identitygh:your-username
in this box.
Create the server
Discourse recommend a server running Ubuntu Long Term Support (LTS), and the expectation would be to use the most recent LTS version. At the time of writing that is Ubuntu 22.04.
You can create your server on any cloud platform, but I have included some steps below for creating the server on DigitalOcean using their doctl
command line tool. (note: Pavilion doesn’t receive any remuneration or affiliate income from DigitalOcean, I just use it at the moment)
Create server on DigitalOcean (optional)
Click here to expand DigitalOcean server setup section
Prerequisites
This section of the checklist uses the doctl
command-line tool for Digital Ocean to create a project and provision the server. You will need to have doctl
installed and set up with credentials to connect to your DigitalOcean account.
Extra DigitalOcean placeholder values
Choose a name for the project, which will be used for naming Digital Ocean project and the droplet (server)
This is the SSH key fingerprint that is in your Digital Ocean account, for initial
root
access only
Create the DigitalOcean project
doctl projects create doctl projects create \
--name =PROJECT_NAME= \
--purpose "Web Application"
Create an Ubuntu 22.04 LTS Digital Ocean droplet in that project
doctl compute droplet create =PROJECT_NAME=-discourse \
--size s-2vcpu-2gb \
--image ubuntu-22-04-x64 \
--region lon1 \
--ssh-keys =DO_SSH_PUBKEY= \
--enable-backups
note: you can get info about available --size
, --image
and --region
arguments with:
doctl compute size list
doctl compute image list-distribution
doctl compute region list
Region location may need to vary according to needs of customer
More info: doctl compute droplet create :: DigitalOcean Documentation
Move the new Droplet into your Project
At present you need to move the Droplet into the project manually in the UI, because although it’s possible from the command line using the doctl projects resources assign ...
command, you would need both the Project and Resource UUID for this and it starts to get tedious.
Enable Digital Ocean Firewall
For now this is a manual step. You may already have a firewall created in the DO panel, which you can add to the Droplet. Information on doing this programmatically is here How To Secure Web Server Infrastructure With DigitalOcean Cloud Firewalls Using Doctl | DigitalOcean
SSH access to the droplet
doctl
simplifies SSH access for you by aliasing droplet name to user/IP
doctl compute ssh =PROJECT_NAME=-discourse
if you’re using the snap
installed version of doctl
then you need to run snap connect doctl:ssh-keys :ssh-keys
first to make it work.
Domain registration and DNS record setup
If you haven’t already registered the Top Level Domain (TLD) that you are going to use for the project, you should do this now.
If you have a domain you want to use, set up an A record in the DNS settings pointing from your =DOMAIN_NAME= to the IP address which your server is located at. This IP address should be visible in the control panel of the cloud platform in which you have created your server.
Log into the server
ssh root@=DOMAIN_NAME=
Set up the server
based on https://thepavilion.io/t/initial-ubuntu-server-setup/1780
all the below commands are executed over SSH on the Droplet
Some useful initial timesaving command aliases
Add doupdates
manual updater for the OS
This adds a command to etc/profile
that speeds up running updates on your servers
echo "alias doupdates='sudo apt-get update && \
sudo apt-get -y dist-upgrade && \
sudo apt autoremove && \
sudo apt autoclean'" >> /etc/profile;source /etc/profile
Add a command to quickly enter the discourse app container
echo "alias app='sudo su && cd /var/discourse && \
./launcher enter app'" >> /etc/profile;source /etc/profile
Automatically cd
to `/var/discourse/ on login (where else would you be going?)
echo "cd /var/discourse/" >> /etc/profile;source /etc/profile
Load those aliases into the current shell session
source /etc/profile
Ubuntu Updates
using the aliases we’ve installed, updating server OS is now a single command:
doupdates
Non-root user setup
This section sets up a non-root user, which is what we will in future use for all logins to the server. We will disable root logins in a later step, for additional security.
You should be logged in over SSH, as root
, to start with.
create a non-root user ‘=NEW_USERNAME=’
After this command you will be prompted for a password. I make up a long complex random password and then forget it because you will never need to use it for this user to login or achieve sudo.
adduser =NEW_USERNAME=
make the new user a sudoer
usermod -aG sudo =NEW_USERNAME=
edit sudo config so that discourse user can sudo without password
This is not a security compromise since the user can only log in using an SSH key, which is very secure
visudo
adding the following after the last line
=NEW_USERNAME= ALL=(ALL) NOPASSWD: ALL
create an .ssh directory for the new user, and change the ownership of that directory to the new user
mkdir /home/=NEW_USERNAME=/.ssh && \
chown -R =NEW_USERNAME=:=NEW_USERNAME= /home/=NEW_USERNAME=/.ssh
become the new user
su - =NEW_USERNAME=
import the required SSH public key to this user’s authorized_keys
file
ssh-import-id =NEW_USER_SSH_IMPORT=
check it worked (optional)
cat ~/.ssh/authorized_keys
This should list the new SSH key as ‘authorized’
exit
Log out and try logging in as the new user
Plain SSH login
ssh =NEW_USERNAME=@=DOMAIN_NAME=
Should log in without requiring a password.
doctl
login
doctl compute ssh =PROJECT_NAME=-discourse --ssh-user =NEW_USERNAME=
Should return =NEW_USERNAME=@=PROJECT_NAME=-discourse:~$
SSH security configuration
edit the SSH config
sudo nano /etc/ssh/sshd_config
edit the SSH config so that the following are set to no
and are uncommented
PermitRootLogin no
PasswordAuthentication no
then apply the changes
sudo service ssh restart
test this by logging out and back in again
exit
root login should now fail
doctl compute ssh =PROJECT_NAME=-discourse --ssh-user root
password login should fail
doctl compute ssh =PROJECT_NAME=-discourse --ssh-user somerandomusername
test login as =NEW_USERNAME= should still work
doctl compute ssh =PROJECT_NAME=-discourse --ssh-user =NEW_USERNAME=
Install Discourse
The following simply follows the Discourse simple installer at https://github.com/discourse/discourse/blob/master/docs/INSTALL-cloud.md
sudo -s
git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
Run Discourse Setup which will install Docker if needed, and then it proceeds with the rest of installation.
./discourse-setup
Hostname
You will need a hostname, not an IP address, in order to set up Discourse properly. Discourse setup will ask you for this hostname as you go through the steps, and you can enter this:
=DOMAIN_NAME=
Then you will be taken through steps including Admin email, SMTP settings, and LetsEncrypt.
Assuming all the above has gone correctly, you should now have a new Discourse at
Congratulations
Next Steps: CHECKLIST: Next steps after installing a new Discourse