Add Heroku deployment support
This commit is contained in:
		
							
								
								
									
										13
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								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.
 | 
					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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[](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
 | 
					## 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.
 | 
					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.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										91
									
								
								app.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								app.json
									
									
									
									
									
										Normal file
									
								
							@@ -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"
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -7,4 +7,4 @@ test:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
production:
 | 
					production:
 | 
				
			||||||
  adapter: redis
 | 
					  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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,10 +45,20 @@ Rails.application.configure do
 | 
				
			|||||||
  # Use a different logger for distributed setups.
 | 
					  # Use a different logger for distributed setups.
 | 
				
			||||||
  # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
 | 
					  # 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.
 | 
					  # Use a different cache store in production.
 | 
				
			||||||
  config.cache_store = :redis_store, {
 | 
					  config.cache_store = :redis_store, {
 | 
				
			||||||
    host: ENV.fetch('REDIS_HOST') { 'localhost' },
 | 
					    host: ENV.fetch('REDIS_HOST') { 'localhost' },
 | 
				
			||||||
    port: ENV.fetch('REDIS_PORT') { 6379 },
 | 
					    port: ENV.fetch('REDIS_PORT') { 6379 },
 | 
				
			||||||
 | 
					    password: ENV.fetch('REDIS_PASSWORD') { false },
 | 
				
			||||||
    db: 0,
 | 
					    db: 0,
 | 
				
			||||||
    namespace: 'cache',
 | 
					    namespace: 'cache',
 | 
				
			||||||
    expires_in: 20.minutes
 | 
					    expires_in: 20.minutes
 | 
				
			||||||
@@ -85,7 +95,7 @@ Rails.application.configure do
 | 
				
			|||||||
    :address        => ENV['SMTP_SERVER'],
 | 
					    :address        => ENV['SMTP_SERVER'],
 | 
				
			||||||
    :user_name      => ENV['SMTP_LOGIN'],
 | 
					    :user_name      => ENV['SMTP_LOGIN'],
 | 
				
			||||||
    :password       => ENV['SMTP_PASSWORD'],
 | 
					    :password       => ENV['SMTP_PASSWORD'],
 | 
				
			||||||
    :domain         => config.x.local_domain,
 | 
					    :domain         => ENV['SMTP_DOMAIN'] || config.x.local_domain,
 | 
				
			||||||
    :authentication => :plain,
 | 
					    :authentication => :plain,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,5 +3,6 @@
 | 
				
			|||||||
Redis.current = Redis.new(
 | 
					Redis.current = Redis.new(
 | 
				
			||||||
  host: ENV.fetch('REDIS_HOST') { 'localhost' },
 | 
					  host: ENV.fetch('REDIS_HOST') { 'localhost' },
 | 
				
			||||||
  port: ENV.fetch('REDIS_PORT') { 6379 },
 | 
					  port: ENV.fetch('REDIS_PORT') { 6379 },
 | 
				
			||||||
 | 
					  password: ENV.fetch('REDIS_PASSWORD') { false },
 | 
				
			||||||
  driver: :hiredis
 | 
					  driver: :hiredis
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,11 @@
 | 
				
			|||||||
host = ENV.fetch('REDIS_HOST') { 'localhost' }
 | 
					host = ENV.fetch('REDIS_HOST') { 'localhost' }
 | 
				
			||||||
port = ENV.fetch('REDIS_PORT') { 6379 }
 | 
					port = ENV.fetch('REDIS_PORT') { 6379 }
 | 
				
			||||||
 | 
					password = ENV.fetch('REDIS_PASSWORD') { false }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Sidekiq.configure_server do |config|
 | 
					Sidekiq.configure_server do |config|
 | 
				
			||||||
  config.redis = { host: host, port: port }
 | 
					  config.redis = { host: host, port: port, password: password}
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Sidekiq.configure_client do |config|
 | 
					Sidekiq.configure_client do |config|
 | 
				
			||||||
  config.redis = { host: host, port: port }
 | 
					  config.redis = { host: host, port: port, password: password }
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,11 @@ preload_app!
 | 
				
			|||||||
# cannot share connections between processes.
 | 
					# cannot share connections between processes.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
on_worker_boot do
 | 
					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)
 | 
					  ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user