# Discourse Install Guide on Ubuntu ## What kind of hardware do you have? - Recommended minimum configuration is: - 2 GB of RAM - 2 GB of swap - 2 processor cores - With 2GB of memory and dual cores, you can run two instances of the thin server (`NUM_WEBS=2`) 1 GB of memory, 3GB 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. ## Install Ubuntu Server 12.04 LTS with the package groups: ![screenshot of package group selection screen](https://raw.github.com/discourse/discourse-docimages/master/install/ubuntu%20-%20install%20-%20software%20selection.png) * Basic Ubuntu server * OpenSSH server * Mail server * PostgreSQL database (9.1+) 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 ### Configure the mail server: ![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) 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. ![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 Install necessary packages: # Run these commands as your normal login (e.g. "michael") sudo apt-get -y install build-essential libssl-dev libyaml-dev git libtool libxslt-dev libxml2-dev libpq-dev gawk curl pngcrush ## Caching: Redis 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: sudo add-apt-repository ppa:rwky/redis sudo apt-get update sudo apt-get install redis-server ## 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 At Discourse, we recommend the latest version of nginx (we like the new and shiny). To install on Ubuntu: # 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 ## Install Ruby with RVM ### RVM : Single-user installation We recommend installing RVM isolated to a single user's environment. ## Discourse setup Create Discourse user: # Run these commands as your normal login (e.g. "michael") sudo adduser --shell /bin/bash discourse Give Postgres database rights to the `discourse` user: # Run these commands as your normal login (e.g. "michael") sudo -u postgres createuser -s discourse 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 Install RVM # As 'discourse' # Install RVM \curl -s -S -L https://get.rvm.io | bash -s stable . ~/.bash_profile # rvm added shell initialization code to ~/.bash_profile, # move it to ~/.profile instead cat ~/.bash_profile >> ~/.profile rm ~/.bash_profile # Install necessary packages for building ruby rvm requirements # 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: Continue with Discourse installation # Build and install ruby rvm install 2.0.0 # Use installed ruby as default rvm use 2.0.0 --default # Install bundler gem install bundler # Pull down the latest release git clone git://github.com/discourse/discourse.git cd discourse git checkout latest-release # Install necessary gems bundle install --deployment --without test _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._ Configure Discourse: # Run these commands as the discourse user cd ~/discourse/config 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 Edit ~/discourse/config/database.yml - 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` - change `host_names` to the name you'll use to access the discourse site, e.g. "forum.example.com" Edit ~/discourse/config/redis.yml - no changes if this is the only application using redis, but have a look Edit ~/discourse/config/discourse.pill - change application name from 'discourse' if necessary - Ensure appropriate Bluepill.application line is uncommented - search for "host to run on" and change to current hostname - note: clockwork should run on only one host Edit ~/discourse/config/initializers/secret_token.rb - uncomment secret_token line - replace SET_SECRET_HERE with secret output from 'RAILS_ENV=production rake secret' command in discourse directory - delete the lines below as per instructions in the file Edit ~/discourse/config/environments/production.rb - 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)) - 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). Initialize the database: # Run these commands as the discourse user # The database name here should match the production one in database.yml cd ~/discourse createdb discourse_prod RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile Not english? Set the default language as appropriate: # Run these commands as the discourse user cd ~/discourse RAILS_ENV=production bundle exec rails c SiteSetting.default_locale = 'fr' # Not sure if your locale is supported? Check at the rails console: LocaleSiteSetting.values => ["cs", "da", "de", "en", "es", "fr", "id", "it", "nb_NO", "nl", "pseudo", "pt", "ru", "sv", "zh_CN", "zh_TW"] ## nginx setup # Run these commands as your normal login (e.g. "michael") sudo cp ~discourse/discourse/config/nginx.sample.conf /etc/nginx/conf.d/discourse.conf Edit /etc/nginx/nginx.conf: - add: `server_names_hash_bucket_size 64;` to the `http` section 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. Edit /etc/nginx/conf.d/discourse.conf - 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 Reload nginx by running # Run as your normal login (e.g. "michael") sudo /etc/init.d/nginx reload ## Bluepill setup Configure Bluepill: # Run these commands as the discourse user gem install bluepill echo 'alias bluepill="NOEXEC_DISABLE=1 bluepill --no-privileged -c ~/.bluepill"' >> ~/.bash_aliases rvm wrapper $(rvm current) bootup bluepill rvm wrapper $(rvm current) bootup bundle Start Discourse: # Run these commands as the discourse user RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=~/discourse RAILS_ENV=production NUM_WEBS=2 bluepill --no-privileged -c ~/.bluepill load ~/discourse/config/discourse.pill Add the Bluepill startup to crontab. # Run these commands as the discourse user crontab -e Add the following lines: @reboot RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=~/discourse RAILS_ENV=production NUM_WEBS=2 /home/discourse/.rvm/bin/bootup_bluepill --no-privileged -c ~/.bluepill load ~/discourse/config/discourse.pill ## Log rotation setup # Disabled for now - log rotation isn't *quite* complete #0 0 * * * /usr/sbin/logrotate ~/discourse/config/logrotate.conf Congratulations! You've got Discourse installed and running! 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 cd ~/discourse RAILS_ENV=production bundle exec rails c # (in rails console) > me = User.find_by_username_or_email('myemailaddress@me.com') > me.activate #use this in case you haven't configured your mail server and therefore can't receive the activation mail. > me.admin = true > me.save 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. ## Site localization Custom assets such as images should be placed somewhere under: DISCOURSE_HOME/public/ For example, create a `local` directory and place it into: DISCOURSE_HOME/public/uploads/local/michael.png The corresponding site setting is: logo_small_url: /uploads/local/michael.png ## Updating Discourse # Run these commands as the discourse user bluepill stop 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 tar cfz ~/discourse-dir-$DATESTAMP.tar.gz -C ~ discourse # Pull down the latest release cd ~/discourse git checkout master git pull git fetch --tags # To run on the latest version instead of bleeding-edge: #git checkout latest-release # # Follow the section below titled: # "Check sample configuration files for new settings" # bundle install --without test --deployment RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile # restart bluepill crontab -l # Here, run the command to start bluepill. # Get it from the crontab output above. Note that if bluepill *itself* needs to be restarted, it must be killed with `bluepill quit` and restarted with the same command that's in crontab ### 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 cd ~/discourse 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 --- config/discourse.pill.sample 2013-07-15 17:38:06.501507001 +0000 +++ config/discourse.pill 2013-07-05 06:38:27.133506896 +0000 @@ -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) adding the `client_max_body_size 2m;` directive to the nginx.conf. This change should also be made to your production file.