At Nanobox, because of the nature of our product, we get a lot of tough questions. Anything from how to use our product to questions about various different languages and frameworks. We’ve been using Slack not only as an internal communication tool, but also as the main method of support for our users. It makes it very easy to help trouble shoot issues, and answer their questions. But, we find ourselves answering a lot of the same questions over and over again as new users join.
Naturally, we figured it was time to set up a forum. A forum would give us a place to put the answers to all the questions we get. We would then be able to direct people where to find answer to all the great questions we get.
We looked for quite some time for what would best fill our needs. There were a few good options out there but ultimately we landed on Discourse. The amount of stuff you get for the price tag (free) with Discourse is quite amazing. The team at Discourse has done a great job.
It has everything you would expect from a full-featured forum platform. Also, there are tons of great official, and community, plugins for anything you feel like it’s missing out of the box.
Discourse has creating an officially supported Docker installation. Which is very cool. They’re very very (very) adamant you use this. And have made it clear that not doing so comes at the cost of support:
I don’t call this out because I think there is anything wrong with what they’re doing. In fact the exact opposite. I think it makes complete sense. How could a small team be expected to support so many possible installs of their project?
I totally sympathize with the demands users put on a development team. Especially for a project that provides as much value as Discourse. I think it’s great they’ve taken the time to create such an easy installation method.
But…
You’re here because for whatever reason you don’t want to use their Docker install. That’s fine, I’ll show you how to run Discourse “without” Docker.
The reason I’m here is because I was tasked with setting up Discourse as our official forum. I could have easily followed their guide and had it up and running quickly. However, just like Discourse uses their own product as their official forum, it was important to me that I use our product as the method for deploying it.
Docker is a very powerful tool that has changed the way we think about web applications, but it requires a lot out of developers to learn, understand, and use. It’s not necessarily difficult, but there is a time investment to getting comfortable with it for sure.
Creating a “Dockerized” version of Discourse makes it much easier to control the outcome of every install. This really helps the team at Discourse ensure that their users have as good an experience as possible. That’s the same reason Nanobox exists. Not all developers have the time or talent available to be full time application developers and full-stack, DevOps, system administrators. Nanobox fills that gap.
Let me reiterate. The process I followed goes directly against Discourse’s recommended procedure. Proceed at your own risk…
I won’t go into all the details of how to deploy Discourse with Nanobox (you can read about that on our blog). I’ll be talking more about my experience trying to get Discourse running using Nanobox.
Normally a “traditional” Rails app is very easy to deploy using Nanobox. In fact, our very own dashboard is a very large and complex Rails app that we’ve deployed to DigitalOcean using Nanobox.
Discourse is anything but a traditional Rails application. They do have various “getting started” guides ranging from beginner to advanced. Most of which only help you get Discourse running locally. You’re left to figure out production deploys on your own.
I read through their requirements list to get a good idea of what I’d need to start with. At the very least I was going to need Ruby, Rails, Postgres, and Redis.
This was my initial boxfile.yml
configuration:
run.config:engine: rubyextra_packages:- nodejs- nginx
data.db:image: nanobox/postgresql:9.4
data.redis:image: nanobox/redis
I modified the config/boot.rb
so that the server would bind to 0.0.0.0
allow access from the outside world, and the config/database.yml
so the app could connect to the database.
After running a rake db:migrate
I tried to start the app. I noticed immediately I was missing some additional packages Discourse needed, so I made the following modifications to my boxfile.yml
:
run.config:engine: rubyextra_packages:- git- nodejs- nginx- ImageMagick- optipng- jpegoptim- gifsicle- jheadextra_steps:- yarn installextra_path_dirs:- node_modules/.bincache_dirs:- .bundle- vendor/bundle- node_modules
This gave me enough to get the application running locally. My next task was to get it deployed to production. This is where things got difficult…
Nanobox lets me stage a production deploy locally with the dry-run
command. This is awesome because I can make sure everything works before I deploy. This turned out to be much more difficult than it should have been. All of my problems stemmed when I tried to precompile assets…
In Rails 3, there was a nice little setting called initialize_on_precompile
. Setting this to false
would tell Rails you didn’t want to initialize the app to precompile all the assets. That was exactly what I wanted. You shouldn’t need to initialize your entire application just to precompile assets.
Turns out, in Rails 4+ they removed this setting. This caused huge issues for me. Now when I was precompiling assets, Discourse was trying to connect to Postgres and Redis.
When running Nanobox locally all services are running, so I never ran into any issues. When trying to deploy however, The services aren’t running when I try to precompile assets (because they don’t need to be).
Nanobox lets you define “hooks” that are run at specific times during the provisioning and deployment process. Well, neither Postgres nor Redis existed when I was trying to precompile assets because neither gets created until later in the process.
I tried to get around this with a few modification to the core application. I thought I’d use an environment variable to skip anything that was trying to connect to either service, so I went around the code adding this:
if ENV["PRECOMPILE"]...
This did NOT work… there are so many dependencies on Postgres and Redis that it was turning into a monster. I took a step back…
Knowing how Nanobox worked, and the requirements of Discourse, I decided that I wasn’t going to be able to compile assets during the build. I’d have to do it in production, after the deploy.
This is not the ideal way to do it, but in the end it worked out ok. I modified the boxfile.yml
one more time to give me a local storage component. Storing the assets here, makes them accessible to anything that needs them.
This is the final boxfile.yml
I used to get Discourse staged and deployed successfully:
You can find info about each different node and what they do in the guide.
There are a couple of strange things in there that you wouldn’t normally see when deploying a Rails application. Luckily the boxfile.yml
is flexible enough that I was able to get everything I needed to get things working.
There were just a few more things that I needed to take care of before everything ran smoothly.
Discourse provides a discourse.conf
file for production configuration. At the top it gives you a few different options on how to use the file.
You can:
At first, I interpreted this to mean that you could use the config file and evars at the same time. After I noticed it wasn’t using some of my evars, I dug into the source and found they are mutually exclusive.
Rather than use half evars and half config file, I ended up using only the config file (I still used evars in the config file, I just wasn’t expecting them to get pulled directly from the environment anymore):
Nanobox automatically generates evars for data services, so I was able to include those in the config right away. Any additional evars I needed, I had to add manually. For example our SMTP credentials:
DISCOURSE_SMTP_ADDRESSDISCOURSE_SMTP_PORTDISCOURSE_SMTP_DOMAINDISCOURSE_SMTP_USER_NAMEDISCOURSE_SMTP_PASSWORD
Even though I didn’t use the evars straight out of the environment I still used the convention Discourse outlined when creating them, and just added them to the config file.
With that all in place, running Discourse on Nanobox turned out to be a breeze. And, while I wasn’t using their official Docker installation, Nanobox uses Docker under the hood, so same thing right?
Discourse was not the traditional Rails application I was hoping it would be. After spending a lot of time digging around in the source code trying to get it working, I found that they’ve overridden, or removed, a lot of what you might expect to find.
All of the initializers are custom, and many standard rake tasks have been completely re-written. They also make a lot of assumptions about the state of the application when you’re trying to run it.
That being said, they’re expecting you to use their Docker image, which works great. So it doesn’t really matter what the underlying application looks like. Once I compensated for all that, the problems went away.
Thanks again to the team at Discourse for such a great project and all the work they’ve done, and continue to do. Now that it’s running, Discourse has worked well for us.
If you’re wanting to get you’re own forum up-and-running with Discourse follow the detailed guide on our blog. If you just want to launch a forum with out doing any work, check out our quickstart.
Please reach out if you run into any issues, or have any questions. You can comment here, or join our Slack team and we’ll do what we can to help.