Merge pull request #1042 from Supermathie/sysadmin-docs

Sysadmin docs
This commit is contained in:
Jeff Atwood 2013-06-18 00:49:12 -07:00
commit 34daa34bc1
7 changed files with 192 additions and 20 deletions

View File

@ -5,6 +5,16 @@ require_relative 'environment'
# These are jobs you should run on a regular basis to make your # These are jobs you should run on a regular basis to make your
# forum work properly. # forum work properly.
def setup_log
Clockwork.configure do |config|
config[:logger].close
config[:logger] = Logger.new(ENV["CLOCK_LOG"])
end if ENV["CLOCK_LOG"]
end
trap('HUP') { setup_log }
setup_log
module Clockwork module Clockwork
handler do |job| handler do |job|
Jobs.enqueue(job, all_sites: true) Jobs.enqueue(job, all_sites: true)

View File

@ -20,11 +20,23 @@ Bluepill.application("discourse", :base_dir => ENV["HOME"] + '/.bluepill') do |a
# getting this to work was a nightmare # getting this to work was a nightmare
# bundle exec spawns a process totally messing with the demonize option # bundle exec spawns a process totally messing with the demonize option
# so we suck the environment out and set it up first # so we suck the environment out and set it up first
app.environment = `env -i BUNDLE_GEMFILE=#{rails_root}/Gemfile /usr/local/rvm/bin/bootup_bundle exec env`.lines.inject({}) do |env_hash,l| bootup_bundle = [ "#{ENV['HOME']}/.rvm/bin/rvm/bootup_bundle",
kv = l.chomp.split('=',2) "/usr/local/rvm/bin/rvm/bootup_bundle",
env_hash[kv[0]] = kv[1] `which bootup_bundle`.strip,
env_hash ].each do |location|
end if File.exist?("/usr/local/rvm/bin/rvm") if File.exist? location
break location
end
end
# XXX if none match, bootup_bundle is set to the array
if bootup_bundle
app.environment = `env -i BUNDLE_GEMFILE=#{rails_root}/Gemfile #{bootup_bundle} exec env`.lines.inject({}) do |env_hash,l|
kv = l.chomp.split('=',2)
env_hash[kv[0]] = kv[1]
env_hash
end
end
app.environment ||= {} app.environment ||= {}
app.environment['RAILS_ENV'] = rails_env app.environment['RAILS_ENV'] = rails_env
@ -37,7 +49,7 @@ Bluepill.application("discourse", :base_dir => ENV["HOME"] + '/.bluepill') do |a
File.directory? sockdir or Dir.mkdir sockdir File.directory? sockdir or Dir.mkdir sockdir
num_webs.times do |i| num_webs.times do |i|
app.process("thin-#{i}") do |process| app.process("thin-#{i}") do |process|
process.start_command = "bundle exec thin start -e production -t 0 --socket #{sockdir}/thin.#{i}.sock -P #{rails_root}/tmp/pids/thin#{i}.pid -d" process.start_command = "bundle exec thin start -e production -t 0 --socket #{sockdir}/thin.#{i}.sock --pid #{rails_root}/tmp/pids/thin#{i}.pid --log #{rails_root}/log/thin-#{i}.log --daemonize"
# Alternatively, you can start with a port number instead of a socket. If you do that, then you MUST update # Alternatively, you can start with a port number instead of a socket. If you do that, then you MUST update
# the upstream section in the nginx config to match. # the upstream section in the nginx config to match.
@ -58,7 +70,7 @@ Bluepill.application("discourse", :base_dir => ENV["HOME"] + '/.bluepill') do |a
#debug instance #debug instance
# app.process("thin-debug") do |process| # app.process("thin-debug") do |process|
# process.start_command = "bundle exec thin start -e development -t 0 -p 10040 -P #{rails_root}/tmp/pids/thin-debug.pid -d" # process.start_command = "bundle exec thin start -e development -t 0 -p 10040 -P #{rails_root}/tmp/pids/thin-debug.pid -l #{rails_root}/log/thin-debug.log" -d"
# process.pid_file = "#{rails_root}/tmp/pids/thin-debug.pid" # process.pid_file = "#{rails_root}/tmp/pids/thin-debug.pid"
# process.start_grace_time = 30.seconds # process.start_grace_time = 30.seconds
# process.stop_grace_time = 10.seconds # process.stop_grace_time = 10.seconds
@ -73,7 +85,7 @@ Bluepill.application("discourse", :base_dir => ENV["HOME"] + '/.bluepill') do |a
app.process("sidekiq-worker") do |process| app.process("sidekiq-worker") do |process|
pidfile = "#{rails_root}/tmp/pids/sidekiq-worker.pid" pidfile = "#{rails_root}/tmp/pids/sidekiq-worker.pid"
process.start_command = "/usr/bin/env PIDFILE=#{pidfile} RAILS_ENV=#{rails_env} bundle exec sidekiq" process.start_command = "/usr/bin/env PIDFILE=#{pidfile} RAILS_ENV=#{rails_env} bundle exec sidekiq -L #{rails_root}/log/sidekiq.log"
process.pid_file = pidfile process.pid_file = pidfile
process.start_grace_time = 30.seconds process.start_grace_time = 30.seconds
process.stop_grace_time = 10.seconds process.stop_grace_time = 10.seconds
@ -83,11 +95,14 @@ Bluepill.application("discourse", :base_dir => ENV["HOME"] + '/.bluepill') do |a
process.daemonize = true process.daemonize = true
end end
if `hostname`.strip == "host to run on" # Perhaps you want to run `hostname -f` here? It depends on your environment
# In any case, ensure the output is what you expect it to be on the system
# running clockwork!
if `hostname -s`.strip == "host to run on"
app.process("clockwork") do |process| app.process("clockwork") do |process|
pidfile = "#{rails_root}/tmp/pids/clockwork.pid" pidfile = "#{rails_root}/tmp/pids/clockwork.pid"
process.start_command = "/usr/bin/env RAILS_ENV=#{rails_env} bundle exec clockwork config/clock.rb" process.start_command = "/usr/bin/env CLOCK_LOG=#{rails_root}/log/clockwork.log RAILS_ENV=#{rails_env} bundle exec clockwork config/clock.rb"
process.pid_file = pidfile process.pid_file = pidfile
process.start_grace_time = 30.seconds process.start_grace_time = 30.seconds
process.stop_grace_time = 10.seconds process.stop_grace_time = 10.seconds

View File

@ -448,7 +448,7 @@ en:
ninja_edit_window: "Number of seconds after posting where edits do not create a new version" ninja_edit_window: "Number of seconds after posting where edits do not create a new version"
max_image_width: "Maximum allowed width of images in a post" max_image_width: "Maximum allowed width of images in a post"
category_featured_topics: "Number of topics displayed per category in the /categories page" category_featured_topics: "Number of topics displayed per category in the /categories page"
add_rel_nofollow_to_user_content: "Add rel nofollow to all submitted user content, except for internal links (including parent domains) changing this requires you update all your baked markdown (<code>rake posts:rebake</code>)" add_rel_nofollow_to_user_content: "Add rel nofollow to all submitted user content, except for internal links (including parent domains) changing this requires you update all your baked markdown with: \"rake posts:rebake\""
exclude_rel_nofollow_domains: "A comma delimited list of domains where nofollow is not added (tld.com will automatically allow sub.tld.com as well)" exclude_rel_nofollow_domains: "A comma delimited list of domains where nofollow is not added (tld.com will automatically allow sub.tld.com as well)"
post_excerpt_maxlength: "Maximum length in chars of a post's excerpt" post_excerpt_maxlength: "Maximum length in chars of a post's excerpt"

40
config/logrotate.conf Normal file
View File

@ -0,0 +1,40 @@
# rotate log files daily, keep 32 days
daily
rotate 32
# create new (empty) log files after rotating old ones
create
compress
missingok
create 0644
/home/discourse/discourse/log/clockwork.log
{
postrotate
pkill -HUP -f clockwork
endscript
}
/home/discourse/discourse/log/sidekiq.log
{
# Should we just kill sidekiq?
# https://github.com/mperham/sidekiq/issues/1008
postrotate
pkill -USR2 -f sidekiq
endscript
}
/home/discourse/discourse/log/production.log
{
# ????
}
/home/discourse/discourse/log/production_errors.log
{
# production_errors is opened on demand, no need to reopen
}
/home/discourse/discourse/log/thin*.log
{
postrotate
pkill -USR1 -f 'thin server'
endscript
}

View File

@ -21,6 +21,13 @@ server {
location / { location / {
root /home/discourse/discourse/public; root /home/discourse/discourse/public;
location ~ \.(jpe?g|png|gif)$ {
valid_referers none blocked mysite.com *.mysite.com;
if ($invalid_referer) {
return 403;
}
}
location ~ ^/t\/[0-9]+\/[0-9]+\/avatar { location ~ ^/t\/[0-9]+\/[0-9]+\/avatar {
expires 1d; expires 1d;
add_header Cache-Control public; add_header Cache-Control public;

View File

@ -204,31 +204,31 @@ Configure Discourse:
cp discourse.pill.sample discourse.pill cp discourse.pill.sample discourse.pill
cp environments/production.rb.sample environments/production.rb cp environments/production.rb.sample environments/production.rb
Edit discourse/config/database.yml Edit ~/discourse/config/database.yml
- change production db name if appropriate - change production db name if appropriate
- change username/password if appropriate - change username/password if appropriate
- set db_id if using multisite - set `db_id` if using multisite
- change `host_names` to the name you'll use to access the discourse site - change `host_names` to the name you'll use to access the discourse site
Edit discourse/config/redis.yml Edit ~/discourse/config/redis.yml
- no changes if this is the only application using redis, but have a look - no changes if this is the only application using redis, but have a look
Edit discourse/config/discourse.pill Edit ~/discourse/config/discourse.pill
- change application name from 'discourse' if necessary - change application name from 'discourse' if necessary
- Ensure appropriate Bluepill.application line is uncommented - Ensure appropriate Bluepill.application line is uncommented
- search for "host to run on" and change to current hostname - search for "host to run on" and change to current hostname
- note: clockwork should run on only one host - note: clockwork should run on only one host
Edit discourse/config/initializers/secret_token.rb Edit ~/discourse/config/initializers/secret_token.rb
- uncomment secret_token line - uncomment secret_token line
- replace SET_SECRET_HERE with secret output from 'rake secret' command in discourse directory - 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 - delete the lines below as per instructions in the file
Edit discourse/config/environments/production.rb Edit ~/discourse/config/environments/production.rb
- check settings, modify smtp settings if necessary - check settings, modify smtp settings if necessary
- See http://meta.discourse.org/t/all-of-my-internal-users-show-as-coming-from-127-0-0-1/6607 if this will serve "internal" users - See http://meta.discourse.org/t/all-of-my-internal-users-show-as-coming-from-127-0-0-1/6607 if this will serve "internal" users
@ -236,10 +236,22 @@ Initialize the database:
# Run these commands as the discourse user # Run these commands as the discourse user
# The database name here should match the production one in database.yml # The database name here should match the production one in database.yml
cd ~/discourse
createdb discourse_prod createdb discourse_prod
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile 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.all_values
=> ["cs", "da", "de", "en", "es", "fr", "id", "it", "nb_NO", "nl", "pseudo", "pt", "ru", "sv", "zh_CN", "zh_TW"]
## nginx setup ## nginx setup
# Run these commands as your normal login (e.g. "michael") # Run these commands as your normal login (e.g. "michael")
@ -248,7 +260,12 @@ Initialize the database:
Edit /etc/nginx/nginx.conf: Edit /etc/nginx/nginx.conf:
- add: `server_names_hash_bucket_size 64;` to the `http` section - add: `server_names_hash_bucket_size 64;` to the `http` section
- uncomment: `gzip on;`
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 /etc/nginx/conf.d/discourse.conf
@ -281,12 +298,18 @@ Add the Bluepill startup to crontab.
# Run these commands as the discourse user # Run these commands as the discourse user
crontab -e crontab -e
Add the following line: Add the following lines:
@reboot RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=~/discourse RAILS_ENV=production NUM_WEBS=4 /home/discourse/.rvm/bin/bootup_bluepill --no-privileged -c ~/.bluepill load ~/discourse/config/discourse.pill @reboot RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=~/discourse RAILS_ENV=production NUM_WEBS=4 /home/discourse/.rvm/bin/bootup_bluepill --no-privileged -c ~/.bluepill load ~/discourse/config/discourse.pill
Note: in case of RVM system-wide installation RVM will be located in `/usr/local/rvm` directory instead of `/home/discourse/.rvm`, so update the line above respectively. Note: in case of RVM system-wide installation RVM will be located in `/usr/local/rvm` directory instead of `/home/discourse/.rvm`, so update the line above respectively.
## 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! Congratulations! You've got Discourse installed and running!
Now make yourself an administrator account. Browse to your discourse instance Now make yourself an administrator account. Browse to your discourse instance

View File

@ -0,0 +1,77 @@
## Troubleshooting issues with Discourse environments
Are you having trouble setting up Discourse? Here are some basic things to
check before reaching out to the community for help:
1. Are you running Ruby 1.9.3 or later?
Discourse is designed for Ruby 1.9.3 or later. You can check your version by
typing `ruby -v` and checking the response.
2. Are you on Postgres 9.1 or later with HSTORE enabled?
You can check your postgres version by typing `psql --version`. To see if hstore is
installed, open a session to postgres and type `\dx` and see if hstore is listed.
3. Have you run `bundle install`?
We frequently update our dependencies to newer versions. It is a good idea to run
`bundle install` every time you check out Discourse, especially if it's been a while.
4. Did you run `bundle update`?
Don't. Running `bundle update` will download gem versions that we haven't tested with.
The Gemfile.lock has the gem versions that Discourse currently uses, so `bundle install`
will work. If you ran update, then you should uninstall the gems, run
`git checkout -- Gemfile.lock` and then run `bundle install`.
5. Have you migrated your database?
Our schema changes fairly frequently. After checking out the source code, you should
run `rake db:migrate`
6. Have you added the seed data?
We depend on some basic seed data being present in the database. You should run
`rake db:seed_fu` to keep your database in sync.
7. Do the tests pass?
If you are having other problems, it's useful to know if the test suite passes. You
can run it by first using `rake db:test:prepare` and then `rake spec`. If you
experience any failures, that's a bad sign! Our master branch should *always* pass
every test.
8. Have you updated host_names in your database.yml?
If links in emails have localhost in them, then you are still using the default host_names
value in database.yml. Update it to use your site's host name(s).
9. Are you having problems bundling:
```
ArgumentError: invalid byte sequence in US-ASCII
An error occurred while installing active_model_serializers (0.7.0), and Bundler cannot continue.
Make sure that `gem install active_model_serializers -v '0.7.0'` succeeds before bundling.
```
Try this in console:
```
$ export LANG="en_US.UTF-8"
$ export LC_ALL="en_US.UTF-8"
```
And/or this in top of `Gemfile`:
```
if RUBY_VERSION =~ /1.9/
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8
end
```