First of all, remove all your A and CNAME records that are relevant to your DigitalOcean box. We’re gonna reconfigure them.
First add an A for mydomain.com
record that points to the IP of your server. Next, add a CNAME s.mydomain.com
and point it to mydomain.com
. This will point both those domains at the exact same spot.
Next we need to do some configuration on your server. Get into your SSH and install nginx
.
Head into /etc/nginx
as root, and create a new directory in there called sites-enabled
. This is simply for convenience so that you know everything in there is a website on your server that’s enabled and ready to be used.
Then go into your /etc/nginx/nginx.conf
as root using your favorite text editor, remove all the server { }
blocks (including the ones that are commented out with #
s). We don’t need them.
Once you’ve deleted them, place include /etc/nginx/sites-enabled/*;
in the spot where those server
blocks once were. This will tell nginx to look in that folder and read every file as part of the nginx config file.
Save the file and exit back to your shell, and run nginx -t
as root to tell nginx to test its config file for errors. If you see something along the lines of test is successful
you can continue on. If not, pay attention to the error message - it’ll give you info on how to fix your config file. ALWAYS run nginx -t
any time you modify the config, get into the habit of doing that so you don’t accidentally apply a bad config.
Now go into that sites-enabled
folder, and as root, create a new file called mydomain.com
. Name all your files in this folder after the domain name of the website you’re configuring - just for organisation purposes.
In mydomain.com, paste this in. Of course, change your server_name
to the right domain name!
No SSL
server {
listen 80; listen [::]:80;
server_name mydomain.com;
index index.html index.htm;
root /usr/share/nginx/html;
}
SSL
# HTTP redirect to HTTPS.
server {
listen 80; listen [::]:80;
server_name mydomain.com;
return 301 https://$http_host$request_uri;
}
# SSL for mydomain.com
server {
listen 443 ssl; listen [::]:443 ssl;
server_name mydomain.com;
ssl on;
ssl_certificate /path/to/ssl/certificate.crt;
ssl_certificate_key /path/to/ssl/private.key;
ssl_session_tickets off;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-D$
http2_idle_timeout 5m; # up from 3m default
root /usr/share/nginx/html;
location / {
index index.html index.htm;
}
}
Note: I’m going to always give two versions of the config files in nginx, one for SSL and one for no SSL. Also, CloudFlare gives you a free Universal SSL certificate that’ll work on your root domain mydomain.com
and any subdomains. If you decide to use the SSL configs I provide (which is highly recommended), use that SSL certificate if you don’t already have one.
Now for Discourse - we want to tell nginx to proxy traffic going toward s.mydomain.com
to your Discourse instance. We don’t want the Discourse instance directly exposed to the Internet because that’ll break things.
First head into your /var/discourse/containers/app.yml
, and head to the expose:
section. Remove these entries:
- "80:80"
- "443:443"
and replace them with
- "81:80"
You don’t need Discourse to have SSL. Discourse won’t be exposed to the Internet, it’s going to be nginx’s slave. Nginx will handle your SSL.
What we’re doing is telling Discourse to expose port 80 on its docker container to port 81 on your host machine. This does two things.
- Stops Discourse from conflicting with nginx, they can run concurrently
- Makes Discourse inaccessible directly on the Internet - for security reasons. Make sure you’re using a port that is BLOCKED on the firewall so traffic isn’t allowed in. Firewall won’t affect local traffic, so nginx will be able to talk to discourse, but, I can’t - for example - without going through nginx.
Be sure to /var/discourse/launcher rebuild app
so the new config applies.
Once that’s done, add another file to your /etc/nginx/sites-enabled
, for your subdomain.
Paste the following config into it:
SSL
# HTTP redirect to security
server {
listen 80; listen [::]:80;
server_name s.mydomain.com;
return 301 https://$http_host$request_uri;
}
# Discourse proxy
server {
listen 443 ssl; listen [::]:443 ssl;
server_name s.mydomain.com;
ssl on;
ssl_certificate /path/to/ssl/certificate.crt;
ssl_certificate_key /path/to/ssl/private.key;
ssl_session_tickets off;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-D$
http2_idle_timeout 5m; # up from 3m default
location / {
proxy_pass http://127.0.0.1:81/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
No SSL
# Discourse proxy
server {
listen 80 ssl; listen [::]:80 ssl;
server_name s.mydomain.com;
http2_idle_timeout 5m; # up from 3m default
location / {
proxy_pass http://127.0.0.1:81/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
This will get Nginx to proxy traffic to your Discourse instance. Once you know all your configs are good, go ahead and start the nginx daemon (systemctl start nginx
or systemctl restart nginx
if it’s already running), then systemctl enable nginx
so it starts on boot.
Now go ahead and navigate to your website in your browser. If things go well, you should see a “Welcome to Nginx” page when you go to mydomain.com
, and Discourse when you go to s.mydomain.com
.
Now you’re free to put anything you want in your /usr/share/nginx/html
to modify the contents of your root domain, without affecting Discourse.