2013-07-30 17:34:31 -04:00
# Official Discourse Install Guide
2013-05-20 17:28:29 -04:00
2013-07-30 17:34:31 -04:00
## Recommended Server Hardware
2013-07-04 03:38:24 -04:00
2013-07-30 17:34:31 -04:00
- 2 GB of RAM
- 2 GB of swap
- 2 processor cores
2013-08-01 18:36:23 -04:00
With 2 GB of memory and dual cores, you can run two instances of the thin server (`NUM_WEBS=2`), and easily host anything but the largest of forums.
2013-07-04 03:38:24 -04:00
2013-08-01 18:36:23 -04:00
1 GB of memory, 3 GB of swap and a single core CPU are the minimums for a steady state, running Discourse forum – but it's simpler to just throw a bit more hardware at the problem if you can, particularly during the install.
2013-07-04 03:38:24 -04:00
2013-06-14 03:30:26 -04:00
## Install Ubuntu Server 12.04 LTS with the package groups:
2013-05-20 17:28:29 -04:00
2013-07-30 17:34:31 -04:00
Yes, you can in theory pick the distro of your choice, but to keep this guide sane, we're picking one, and it's Ubuntu. Feel free to substitute the distro of your choice, the steps are mostly the same.
2013-06-05 03:33:20 -04:00
![screenshot of package group selection screen ](https://raw.github.com/discourse/discourse-docimages/master/install/ubuntu%20-%20install%20-%20software%20selection.png )
2013-06-14 03:30:26 -04:00
* Basic Ubuntu server
2013-05-20 17:28:29 -04:00
* OpenSSH server
* Mail server
* PostgreSQL database (9.1+)
2013-06-05 03:33:20 -04:00
You may be working on an already-installed or automatically deployed system, in which case you can install them afterwards:
# Run these commands as your normal login (e.g. "michael")
sudo apt-get update & & sudo apt-get -y upgrade
sudo tasksel install openssh-server
sudo tasksel install mail-server
sudo tasksel install postgresql-server
2013-05-20 17:28:29 -04:00
### Configure the mail server:
2013-06-05 03:33:20 -04:00
![screenshot of mail server type configuration screen ](https://raw.github.com/discourse/discourse-docimages/master/install/ubuntu%20-%20install%20-%20mail_1%20system%20type.png )
2013-05-20 17:28:29 -04:00
In our example setup, we're going to configure as a 'Satellite system', forwarding all mail to our egress servers for delivery. You'll probably want to do that unless you're handling mail on the same machine as the Discourse software.
2013-06-05 03:33:20 -04:00
![screenshot of mail name configuration screen ](https://raw.github.com/discourse/discourse-docimages/master/install/ubuntu%20-%20install%20-%20mail_2%20mailname.png )
You probably want to configure your 'mail name' to be the base name of your domain. Note that this does not affect any email sent out by Discourse itself, just unqualified mail generated by systems programs.
![screenshot of relay host configuration screen ](https://raw.github.com/discourse/discourse-docimages/master/install/ubuntu%20-%20install%20-%20mail_3%20relayconfig.png )
If you have a mail server responsible for handling the egress of email from your network, enter it here. Otherwise, leave it blank.
## Additional system packages
2013-05-20 17:28:29 -04:00
Install necessary packages:
# Run these commands as your normal login (e.g. "michael")
2013-08-07 00:06:40 -04:00
sudo apt-get -y install build-essential libssl-dev libyaml-dev git libtool libxslt-dev libxml2-dev libpq-dev gawk curl pngcrush python-software-properties
2013-07-17 19:11:20 -04:00
2013-08-13 12:09:43 -04:00
# If you're on Ubuntu >= 12.10, change:
# python-software-properties to software-properties-common
2013-08-07 13:25:05 -04:00
## Caching: Redis
2013-07-23 02:33:11 -04:00
Redis is a networked, in memory key-value store cache. Without the Redis caching layer, we'd have to go to the database a lot more often for common information and the site would be slower as a result.
Be sure to install the latest stable Redis, as the package in the distro may be a bit old:
2013-07-17 19:11:20 -04:00
2013-08-07 00:06:40 -04:00
sudo apt-add-repository -y ppa:rwky/redis
2013-07-17 19:11:20 -04:00
sudo apt-get update
sudo apt-get install redis-server
2013-05-20 17:28:29 -04:00
2013-07-21 03:42:07 -04:00
## Web Server: nginx
nginx is used for:
* reverse proxy (i.e. load balancer)
* static asset serving (since you don't want to do that from ruby)
* anonymous user cache
2013-05-20 17:28:29 -04:00
2013-05-24 23:25:03 -04:00
At Discourse, we recommend the latest version of nginx (we like the new and
shiny). To install on Ubuntu:
2013-05-20 17:28:29 -04:00
# Run these commands as your normal login (e.g. "michael")
# Remove any existing versions of nginx
sudo apt-get remove '^nginx.*$'
# Add nginx repo to sources.list
cat < < 'EOF' | sudo tee -a /etc/apt/sources.list
deb http://nginx.org/packages/ubuntu/ precise nginx
deb-src http://nginx.org/packages/ubuntu/ precise nginx
EOF
# Add nginx key
curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add -
# install nginx
sudo apt-get update & & sudo apt-get -y install nginx
2013-05-24 23:25:03 -04:00
2013-06-14 03:30:26 -04:00
## Install Ruby with RVM
2013-05-20 17:28:29 -04:00
2013-07-21 03:42:07 -04:00
### RVM : Single-user installation
2013-05-24 23:25:03 -04:00
2013-07-21 03:42:07 -04:00
We recommend installing RVM isolated to a single user's environment.
2013-05-20 17:28:29 -04:00
## Discourse setup
2013-06-14 03:30:26 -04:00
Create Discourse user:
2013-05-20 17:28:29 -04:00
# Run these commands as your normal login (e.g. "michael")
2013-08-07 00:06:40 -04:00
sudo adduser --shell /bin/bash --gecos 'Discourse application' discourse
sudo install -d -m 755 -o discourse -g discourse /var/www/discourse
2013-05-20 17:28:29 -04:00
2013-06-14 03:30:26 -04:00
Give Postgres database rights to the `discourse` user:
2013-05-20 17:28:29 -04:00
# Run these commands as your normal login (e.g. "michael")
sudo -u postgres createuser -s discourse
2013-08-07 00:06:40 -04:00
# If you will be using password authentication on your database, only
# necessary if the database will be on a remote host
2013-05-20 17:28:29 -04:00
sudo -u postgres psql -c "alter user discourse password 'todayisagooddaytovi';"
Change to the 'discourse' user:
# Run this command as your normal login (e.g. "michael"), further commands should be run as 'discourse'
sudo su - discourse
2013-07-21 03:42:07 -04:00
Install RVM
2013-05-24 23:25:03 -04:00
2013-06-05 03:33:20 -04:00
# As 'discourse'
2013-05-24 23:25:03 -04:00
# Install RVM
\curl -s -S -L https://get.rvm.io | bash -s stable
2013-06-05 03:33:20 -04:00
. ~/.bash_profile
# rvm added shell initialization code to ~/.bash_profile,
# move it to ~/.profile instead
cat ~/.bash_profile >> ~/.profile
rm ~/.bash_profile
2013-05-24 23:25:03 -04:00
2013-08-07 00:06:40 -04:00
# Install necessary packages for building ruby (this will only work if
# you've given discourse sudo permissions, which is *not* the default)
# rvm requirements
2013-05-24 23:25:03 -04:00
# If discourse does not have sudo permissions (likely the case), run:
rvm --autolibs=read-fail requirements
# and rvm will tell you which packages you (or your sysadmin) need
# to install before it can proceed. Do that and then resume next:
2013-06-14 03:30:26 -04:00
Continue with Discourse installation
2013-05-24 23:25:03 -04:00
# Build and install ruby
rvm install 2.0.0
2013-08-07 13:25:05 -04:00
2013-07-23 14:59:03 -04:00
# Use installed ruby as default
rvm use 2.0.0 --default
2013-08-07 13:25:05 -04:00
2013-07-23 14:59:03 -04:00
# Install bundler
2013-05-24 23:25:03 -04:00
gem install bundler
2013-07-30 16:26:08 -04:00
# Pull down the latest code
2013-08-07 00:06:40 -04:00
git clone git://github.com/discourse/discourse.git /var/www/discourse
cd /var/www/discourse
2013-07-30 16:26:08 -04:00
git checkout master
2013-08-07 13:25:05 -04:00
2013-07-30 16:26:08 -04:00
# To run on the most recent numbered release instead of bleeding-edge:
#git checkout latest-release
2013-05-20 17:28:29 -04:00
# Install necessary gems
2013-06-05 03:33:20 -04:00
bundle install --deployment --without test
2013-05-20 23:53:44 -04:00
2013-06-05 03:33:20 -04:00
_If you have errors building the native extensions, ensure you have sufficient free system memory. 1GB with no swap isn't enough, we recommend having 2GB as a minimum._
2013-05-20 17:28:29 -04:00
2013-06-14 03:30:26 -04:00
Configure Discourse:
2013-05-20 17:28:29 -04:00
# Run these commands as the discourse user
2013-08-07 00:06:40 -04:00
cd /var/www/discourse/config
2013-05-24 23:25:03 -04:00
cp database.yml.production-sample database.yml
cp redis.yml.sample redis.yml
cp discourse.pill.sample discourse.pill
cp environments/production.rb.sample environments/production.rb
2013-05-20 17:28:29 -04:00
2013-08-07 00:06:40 -04:00
Edit /var/www/discourse/config/database.yml
2013-05-20 17:28:29 -04:00
2013-07-23 02:38:41 -04:00
- change production database name if appropriate
- change database username/password if appropriate
- if you are hosting multiple Discourse forums on the same server (multisite), set `db_id`
2013-07-23 02:28:05 -04:00
- change `host_names` to the name you'll use to access the discourse site, e.g. "forum.example.com"
2013-05-20 17:28:29 -04:00
2013-08-07 00:06:40 -04:00
Edit /var/www/discourse/config/redis.yml
2013-05-20 17:28:29 -04:00
- no changes if this is the only application using redis, but have a look
2013-08-07 00:06:40 -04:00
Edit /var/www/discourse/config/discourse.pill
2013-05-20 17:28:29 -04:00
2013-05-29 00:07:26 -04:00
- change application name from 'discourse' if necessary
- Ensure appropriate Bluepill.application line is uncommented
2013-05-20 17:28:29 -04:00
- search for "host to run on" and change to current hostname
2013-08-07 00:06:40 -04:00
Edit /var/www/discourse/config/initializers/secret_token.rb
2013-05-29 00:07:26 -04:00
2013-05-20 17:28:29 -04:00
- uncomment secret_token line
2013-08-07 00:06:40 -04:00
- replace SET_SECRET_HERE with the output from 'RAILS_ENV=production rake secret' command run from the discourse directory (`/var/www/discourse`)
2013-05-21 00:12:20 -04:00
- delete the lines below as per instructions in the file
2013-05-20 17:28:29 -04:00
2013-08-07 00:06:40 -04:00
Edit /var/www/discourse/config/environments/production.rb
2013-07-23 02:28:05 -04:00
- browse througn all the settings
- be sure to add your mail server SMTP settings so outgoing mail can be sent (we recommend [Mandrill ](https://mandrillapp.com ))
2013-07-23 02:36:39 -04:00
- If your users will come from "internal" [private unroutable IPs ](https://en.wikipedia.org/wiki/Private_network ) like 10.x.x.x or 192.168.x.x please [see this topic ](http://meta.discourse.org/t/all-of-my-internal-users-show-as-coming-from-127-0-0-1/6607 ).
2013-05-20 17:28:29 -04:00
Initialize the database:
# Run these commands as the discourse user
# The database name here should match the production one in database.yml
2013-08-07 00:06:40 -04:00
cd /var/www/discourse
2013-05-20 17:28:29 -04:00
createdb discourse_prod
2013-06-06 04:58:39 -04:00
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile
2013-05-20 17:28:29 -04:00
2013-06-18 02:28:30 -04:00
Not english? Set the default language as appropriate:
# Run these commands as the discourse user
2013-08-07 00:06:40 -04:00
cd /var/www/discourse
2013-06-18 02:28:30 -04:00
RAILS_ENV=production bundle exec rails c
SiteSetting.default_locale = 'fr'
# Not sure if your locale is supported? Check at the rails console:
2013-06-23 01:07:25 -04:00
LocaleSiteSetting.values
2013-08-07 13:25:05 -04:00
=> ["cs", "da", "de", "en", "es", "fr", "id", "it", "nb_NO", "nl", "pseudo", "pt", "ru", "sv", "zh_CN", "zh_TW"]
2013-06-18 02:28:30 -04:00
2013-05-20 17:28:29 -04:00
## nginx setup
# Run these commands as your normal login (e.g. "michael")
2013-08-07 00:06:40 -04:00
sudo cp /var/www/discourse/config/nginx.sample.conf /etc/nginx/conf.d/discourse.conf
2013-05-20 17:28:29 -04:00
2013-06-06 04:58:39 -04:00
Edit /etc/nginx/nginx.conf:
- add: `server_names_hash_bucket_size 64;` to the `http` section
2013-06-18 02:28:30 -04:00
If discourse will be the only site served by nginx, disable the nginx default
site:
- `sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled`
- Otherwise, only `server_name` s configured below in `discourse.conf` will be passed to Discourse.
2013-06-06 04:58:39 -04:00
2013-05-20 17:28:29 -04:00
Edit /etc/nginx/conf.d/discourse.conf
2013-05-29 00:07:26 -04:00
- edit `server_name` . Example: `server_name cain.discourse.org test.cain.discourse.org;`
- change socket paths if discourse is installed to a different location
- modify root location if discourse is installed to a different location
2013-05-20 17:28:29 -04:00
2013-05-30 19:03:06 -04:00
Reload nginx by running
# Run as your normal login (e.g. "michael")
sudo /etc/init.d/nginx reload
2013-05-20 17:28:29 -04:00
## Bluepill setup
2013-06-14 03:30:26 -04:00
Configure Bluepill:
2013-05-20 17:28:29 -04:00
# Run these commands as the discourse user
gem install bluepill
2013-06-05 03:33:20 -04:00
echo 'alias bluepill="NOEXEC_DISABLE=1 bluepill --no-privileged -c ~/.bluepill"' >> ~/.bash_aliases
2013-05-20 23:53:44 -04:00
rvm wrapper $(rvm current) bootup bluepill
rvm wrapper $(rvm current) bootup bundle
2013-05-20 17:28:29 -04:00
Start Discourse:
# Run these commands as the discourse user
2013-08-07 00:06:40 -04:00
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=/var/www/discourse RAILS_ENV=production NUM_WEBS=2 bluepill --no-privileged -c ~/.bluepill load /var/www/discourse/config/discourse.pill
2013-05-20 17:28:29 -04:00
2013-06-14 03:30:26 -04:00
Add the Bluepill startup to crontab.
2013-05-20 17:28:29 -04:00
# Run these commands as the discourse user
crontab -e
2013-06-15 01:25:41 -04:00
Add the following lines:
2013-05-20 17:28:29 -04:00
2013-08-07 00:06:40 -04:00
@reboot RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=/var/www/discourse RAILS_ENV=production NUM_WEBS=2 /home/discourse/.rvm/bin/bootup_bluepill --no-privileged -c ~/.bluepill load /var/www/discourse/config/discourse.pill
2013-06-13 06:15:58 -04:00
2013-06-18 02:28:30 -04:00
## Log rotation setup
2013-06-18 03:05:12 -04:00
# Disabled for now - log rotation isn't *quite* complete
2013-08-07 00:06:40 -04:00
#0 0 * * * /usr/sbin/logrotate /var/www/discourse/config/logrotate.conf
2013-06-18 02:28:30 -04:00
2013-05-20 17:28:29 -04:00
Congratulations! You've got Discourse installed and running!
2013-05-28 17:46:55 -04:00
2013-06-06 04:58:39 -04:00
Now make yourself an administrator account. Browse to your discourse instance
and create an account by logging in normally, then run the commands:
# Run these commands as the discourse user
2013-08-07 00:06:40 -04:00
cd /var/www/discourse
2013-06-06 04:58:39 -04:00
RAILS_ENV=production bundle exec rails c
2013-08-07 00:06:40 -04:00
# Administratorize yourself:
2013-06-06 04:58:39 -04:00
# (in rails console)
2013-07-01 23:19:52 -04:00
> me = User.find_by_username_or_email('myemailaddress@me.com')
2013-08-07 00:06:40 -04:00
> me.activate # use this in case you haven't configured your mail server and therefore can't receive the activation mail.
2013-06-06 04:58:39 -04:00
> me.admin = true
> me.save
2013-08-07 00:06:40 -04:00
# Mark yourself as the 'system user':
# (in rails console)
> SiteSetting.system_username = me.username
2013-06-26 23:58:29 -04:00
At this point we recommend you start going through the various items in the
[Discourse Admin Quick Start Guide ](https://github.com/discourse/discourse/wiki/The-Discourse-Admin-Quick-Start-Guide )
to further prepare your site for users.
2013-06-24 04:09:43 -04:00
## Site localization
Custom assets such as images should be placed somewhere under:
2013-08-07 00:06:40 -04:00
/var/www/discourse/public/
2013-06-24 04:09:43 -04:00
For example, create a `local` directory and place it into:
2013-08-07 00:06:40 -04:00
/var/www/discourse/public/uploads/local/michael.png
2013-06-24 04:09:43 -04:00
The corresponding site setting is:
logo_small_url: /uploads/local/michael.png
2013-05-28 17:46:55 -04:00
## Updating Discourse
# Run these commands as the discourse user
bluepill stop
2013-07-21 03:42:07 -04:00
bluepill quit
# Back up your install
DATESTAMP=$(TZ=UTC date +%F-%T)
pg_dump --no-owner --clean discourse_prod | gzip -c > ~/discourse-db-$DATESTAMP.sql.gz
2013-08-07 00:06:40 -04:00
tar cfz ~/discourse-dir-$DATESTAMP.tar.gz -C /var/www discourse
2013-07-30 16:26:08 -04:00
# get the latest Discourse code
2013-08-07 00:06:40 -04:00
cd /var/www/discourse
2013-05-28 17:46:55 -04:00
git checkout master
git pull
git fetch --tags
2013-07-30 16:26:08 -04:00
# To run on the latest numbered release instead of bleeding-edge:
2013-05-28 17:46:55 -04:00
#git checkout latest-release
2013-07-21 03:42:07 -04:00
#
# Follow the section below titled:
# "Check sample configuration files for new settings"
#
2013-06-05 03:33:20 -04:00
bundle install --without test --deployment
2013-06-06 04:58:39 -04:00
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile
2013-07-21 03:42:07 -04:00
# restart bluepill
crontab -l
# Here, run the command to start bluepill.
# Get it from the crontab output above.
2013-06-24 04:09:43 -04:00
2013-07-21 03:42:07 -04:00
### Check sample configuration files for new settings
Check the sample configuration files provided in the repo with the ones being used for additional recommended settings and merge those in:
# Run these commands as the discourse user
2013-08-07 00:06:40 -04:00
cd /var/www/discourse
2013-07-21 03:42:07 -04:00
diff -u config/discourse.pill.sample config/discourse.pill
diff -u config/nginx.sample.conf /etc/nginx/conf.d/discourse.conf
diff -u config/environments/production.rb.sample config/environments/production.rb
#### Example 1
$ diff -u config/discourse.pill.sample config/discourse.pill
2013-07-23 02:28:05 -04:00
--- config/discourse.pill.sample 2013-07-15 17:38:06.501507001 +0000
2013-07-30 16:26:08 -04:00
+++ config/discourse.pill 2013-07-05 06:38:27.133506896 +0000
2013-07-21 03:42:07 -04:00
@@ -46,7 +46,7 @@
app.working_dir = rails_root
sockdir = "#{rails_root}/tmp/sockets"
- File.directory? sockdir or FileUtils.mkdir_p sockdir
+ File.directory? sockdir or Dir.mkdir sockdir
num_webs.times do |i|
app.process("thin-#{i}") do |process|
This change reflects us switching to using `FileUtils.mkdir_p` instead of `Dir.mkdir` .
#### Example 2
$ diff -u config/nginx.sample.conf /etc/nginx/conf.d/discourse.conf
--- config/nginx.sample.conf 2013-07-15 17:38:06.521507000 +0000
+++ /etc/nginx/conf.d/discourse.conf 2013-07-15 17:52:46.649507024 +0000
@@ -12,17 +12,18 @@
gzip_min_length 1000;
gzip_types application/json text/css application/x-javascript;
- server_name enter.your.web.hostname.here;
+ server_name webtier.discourse.org;
sendfile on;
keepalive_timeout 65;
- client_max_body_size 2m;
location / {
root /home/discourse/discourse/public;
This change reflects a change in placeholder information plus (importantly)
2013-08-07 00:06:40 -04:00
adding the `client_max_body_size 2m;` directive to the nginx configuration.
This change should also be made to your production file.
2013-07-30 16:41:14 -04:00
## Security
2013-08-07 00:06:40 -04:00
We take security very seriously at Discourse, and all our code is 100% open source and peer reviewed.
Please read [our security guide ](https://github.com/discourse/discourse/blob/master/docs/SECURITY.md ) for an overview of security measures in Discourse.