about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEffy Elden <git@effy.is>2017-01-17 22:00:03 +1100
committerEffy Elden <git@effy.is>2017-01-17 22:00:03 +1100
commitab4f5f5da5229bbc33f3c86815eaf1e057c697b1 (patch)
tree7bab737c8ed6b113e213ba7334d28b6c9855a781
parent6cf44ca92c3b92df5bda32adb59258104f1ac9c5 (diff)
Add Heroku deployment support
-rw-r--r--Procfile1
-rw-r--r--README.md13
-rw-r--r--app.json91
-rw-r--r--config/cable.yml2
-rw-r--r--config/environments/production.rb12
-rw-r--r--config/initializers/redis.rb1
-rw-r--r--config/initializers/sidekiq.rb5
-rw-r--r--config/puma.rb5
8 files changed, 126 insertions, 4 deletions
diff --git a/Procfile b/Procfile
new file mode 100644
index 000000000..c2c566e8c
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: bundle exec puma -C config/puma.rb
diff --git a/README.md b/README.md
index 7e95da41f..4ba402379 100644
--- a/README.md
+++ b/README.md
@@ -118,6 +118,19 @@ Which will re-create the updated containers, leaving databases and data as is. D
 
 Docker is great for quickly trying out software, but it has its drawbacks too. If you prefer to run Mastodon without using Docker, refer to the [production guide](https://github.com/tootsuite/mastodon/wiki/Production-guide) for examples, configuration and instructions.
 
+## Deployment on Heroku (experimental)
+
+[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
+
+Mastodon can theoretically run indefinitely on a free [Heroku](https://heroku.com) app. It should be noted this has limited testing and could have unpredictable results.
+
+1. Click the above button.
+2. Fill in the options requested.
+  * You can use a .herokuapp.com domain, which will be simple to set up, or you can use a custom domain. If you want a custom domain and HTTPS, you will need to upgrade to a paid plan (to use Heroku's SSL features), or set up [CloudFlare](https://cloudflare.com) who offer free "Flexible SSL" (note: CloudFlare have some undefined limits on WebSockets. So far, no one has reported hitting concurrent connection limits).
+  * You will want Amazon S3 for file storage. The only exception is for development purposes, where you may not care if files are not saaved. Follow a guide online for creating a free Amazon S3 bucket and Access Key, then enter the details.
+  * If you want your Mastodon to be able to send emails, configure SMTP settings here (or later). Consider using [Mailgun](https://mailgun.com) or similar, who offer free plans that should suit your interests.
+3. Deploy! The app should be set up, with a working web interface and database. You can change settings and manage versions from the Heroku dashboard.
+
 ## Development with Vagrant
 
 A quick way to get a development environment up and running is with Vagrant. You will need recent versions of [Vagrant](https://www.vagrantup.com/) and [VirtualBox](https://www.virtualbox.org/) installed.
diff --git a/app.json b/app.json
new file mode 100644
index 000000000..c0579d33e
--- /dev/null
+++ b/app.json
@@ -0,0 +1,91 @@
+{
+  "name": "Mastodon",
+  "description": "A GNU Social-compatible microblogging server",
+  "repository": "https://github.com/tootsuite/mastodon",
+  "logo": "https://github.com/tootsuite/mastodon/raw/master/app/assets/images/logo.png",
+  "env": {
+    "HEROKU": {
+      "description": "Leave this as true",
+      "value": "true",
+      "required": true
+    },
+    "LOCAL_DOMAIN": {
+      "description": "The domain that your Mastodon instance will run on (this can be appname.herokuapp.com or a custom domain)",
+      "required": true
+    },
+    "LOCAL_HTTPS": {
+      "description": "Will your domain support HTTPS? (Automatic for herokuapp, requires manual configuration for custom domains)",
+      "value": "false",
+      "required": true
+    },
+    "PAPERCLIP_SECRET": {
+      "description": "The secret key for storing media files",
+      "generator": "secret"
+    },
+    "SECRET_KEY_BASE": {
+      "description": "The secret key base",
+      "generator": "secret"
+    },
+    "SINGLE_USER_MODE": {
+      "description": "Should the instance run in single user mode? (Disable registrations, redirect to front page)",
+      "value": "false",
+      "required": true
+    },
+    "S3_ENABLED": {
+      "description": "Should Mastodon use Amazon S3 for storage? This is highly recommended, as Heroku does not have persistent file storage (files will be lost).",
+      "value": "true",
+      "required": false
+    },
+    "S3_BUCKET": {
+      "description": "Amazon S3 Bucket",
+      "required": false
+    },
+    "S3_REGION": {
+      "description": "Amazon S3 region that the bucket is located in",
+      "required": false
+    },
+    "AWS_ACCESS_KEY_ID": {
+      "description": "Amazon S3 Access Key",
+      "required": false
+    },
+    "AWS_SECRET_ACCESS_KEY": {
+      "description": "Amazon S3 Secret Key",
+      "required": false
+    },
+    "SMTP_SERVER": {
+      "description": "Hostname for SMTP server, if you want to enable email",
+      "required": false
+    },
+    "SMTP_PORT": {
+      "description": "Port for SMTP server",
+      "required": false
+    },
+    "SMTP_LOGIN": {
+      "description": "Username for SMTP server",
+      "required": false
+    },
+    "SMTP_PASSWORD": {
+      "description": "Password for SMTP server",
+      "required": false
+    },
+    "SMTP_DOMAIN": {
+      "description": "Domain for SMTP server. Will default to instance domain if blank.",
+      "required": false
+    }
+  },
+  "buildpacks": [
+    {
+      "url": "heroku/nodejs"
+    },
+    {
+      "url": "heroku/ruby"
+    }
+  ],
+  "scripts": {
+    "postdeploy": "bundle exec rails db:migrate && bundle exec rails db:seed"
+  },
+  "addons": [
+    "heroku-postgresql",
+    "heroku-redis"
+  ]
+}
\ No newline at end of file
diff --git a/config/cable.yml b/config/cable.yml
index 978f721af..34759a772 100644
--- a/config/cable.yml
+++ b/config/cable.yml
@@ -7,4 +7,4 @@ test:
 
 production:
   adapter: redis
-  url: redis://<%= ENV['REDIS_HOST'] || 'localhost' %>:<%= ENV['REDIS_PORT'] || 6379 %>/1
+  url: redis://<%= ENV['REDIS_PASSWORD'] ? ':' + ENV['REDIS_PASSWORD'] + '@' : '' %><%= ENV['REDIS_HOST'] || 'localhost' %>:<%= ENV['REDIS_PORT'] || 6379 %>/1
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 9254d494c..8b8d974b3 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -45,10 +45,20 @@ Rails.application.configure do
   # Use a different logger for distributed setups.
   # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
 
+  # Parse and split the REDIS_URL if passed (used with hosting platforms such as Heroku).
+  # Set ENV variables because they are used elsewhere.
+  if ENV['REDIS_URL']
+    redis_url = URI.parse(ENV['REDIS_URL'])
+    ENV['REDIS_HOST'] = redis_url.host
+    ENV['REDIS_PORT'] = redis_url.port.to_s
+    ENV['REDIS_PASSWORD'] = redis_url.password
+  end
+
   # Use a different cache store in production.
   config.cache_store = :redis_store, {
     host: ENV.fetch('REDIS_HOST') { 'localhost' },
     port: ENV.fetch('REDIS_PORT') { 6379 },
+    password: ENV.fetch('REDIS_PASSWORD') { false },
     db: 0,
     namespace: 'cache',
     expires_in: 20.minutes
@@ -85,7 +95,7 @@ Rails.application.configure do
     :address        => ENV['SMTP_SERVER'],
     :user_name      => ENV['SMTP_LOGIN'],
     :password       => ENV['SMTP_PASSWORD'],
-    :domain         => config.x.local_domain,
+    :domain         => ENV['SMTP_DOMAIN'] || config.x.local_domain,
     :authentication => :plain,
   }
 
diff --git a/config/initializers/redis.rb b/config/initializers/redis.rb
index 3825710b8..3660c4a9b 100644
--- a/config/initializers/redis.rb
+++ b/config/initializers/redis.rb
@@ -3,5 +3,6 @@
 Redis.current = Redis.new(
   host: ENV.fetch('REDIS_HOST') { 'localhost' },
   port: ENV.fetch('REDIS_PORT') { 6379 },
+  password: ENV.fetch('REDIS_PASSWORD') { false },
   driver: :hiredis
 )
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 63fdb3f16..ecdd07b08 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,10 +1,11 @@
 host = ENV.fetch('REDIS_HOST') { 'localhost' }
 port = ENV.fetch('REDIS_PORT') { 6379 }
+password = ENV.fetch('REDIS_PASSWORD') { false }
 
 Sidekiq.configure_server do |config|
-  config.redis = { host: host, port: port }
+  config.redis = { host: host, port: port, password: password}
 end
 
 Sidekiq.configure_client do |config|
-  config.redis = { host: host, port: port }
+  config.redis = { host: host, port: port, password: password }
 end
diff --git a/config/puma.rb b/config/puma.rb
index ad2dbfffd..e6b0da91b 100644
--- a/config/puma.rb
+++ b/config/puma.rb
@@ -40,6 +40,11 @@ preload_app!
 # cannot share connections between processes.
 #
 on_worker_boot do
+
+  if ENV["HEROKU"] #Spwan the workers from Puma, to only use one dyno
+    @sidekiq_pid ||= spawn('bundle exec sidekiq -q default -q mailers -q push')
+  end
+
   ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
 end