diff --git a/roles/mastodon.rb b/roles/mastodon.rb index 28761b2..d5f07a4 100644 --- a/roles/mastodon.rb +++ b/roles/mastodon.rb @@ -1,7 +1,8 @@ name "mastodon" default_attributes 'kosmos-mastodon' => { - 'deploy' => false + 'deploy' => false, + 'build' => false } run_list %w( diff --git a/site-cookbooks/kosmos-mastodon/attributes/default.rb b/site-cookbooks/kosmos-mastodon/attributes/default.rb index 237c46e..5b18556 100644 --- a/site-cookbooks/kosmos-mastodon/attributes/default.rb +++ b/site-cookbooks/kosmos-mastodon/attributes/default.rb @@ -12,6 +12,11 @@ node.default["kosmos-mastodon"]["sidekiq_threads"] = 25 # is true. Set to false to only install the runtime dependencies. node.default["kosmos-mastodon"]["deploy"] = true +# Only check out and build the application (no migrations, no services) when +# this is true. Implied by `deploy`. Useful to pre-stage a deployment without +# touching the database. +node.default["kosmos-mastodon"]["build"] = true + # Runtime versions node.default["kosmos-mastodon"]["nodejs_version"] = "24.21.0" node.default["kosmos-mastodon"]["ruby_version"] = "4.0.7" diff --git a/site-cookbooks/kosmos-mastodon/recipes/build.rb b/site-cookbooks/kosmos-mastodon/recipes/build.rb new file mode 100644 index 0000000..95b6b99 --- /dev/null +++ b/site-cookbooks/kosmos-mastodon/recipes/build.rb @@ -0,0 +1,141 @@ +# +# Cookbook Name:: kosmos-mastodon +# Recipe:: build +# +# Checks out and builds the application without running migrations or starting +# any services, so a deployment can be pre-staged before the maintenance +# window. The build is skipped while the checked-out revision is unchanged. +# + +require 'uri' + +postgresql_credentials = data_bag_item('credentials', 'postgresql') + +mastodon_path = node["kosmos-mastodon"]["directory"] +mastodon_user = "mastodon" + +ruby_version = node["kosmos-mastodon"]["ruby_version"] +ruby_path = "/opt/ruby_build/builds/#{ruby_version}" + +# External Redis cluster (see the kosmos_redis cookbook) +redis_host = search(:node, "role:#{node['kosmos-mastodon']['redis_server_role']}").first&.dig("knife_zero", "host") + +if redis_host.nil? + Chef::Log.fatal("No node found with '#{node['kosmos-mastodon']['redis_server_role']}' role. Stopping here.") + return +end + +redis_password = URI.encode_www_form_component(data_bag_item('credentials', 'redis')['password']) +redis_url = "redis://:#{redis_password}@#{redis_host}:#{node['kosmos-mastodon']['redis_port']}/#{node['kosmos-mastodon']['redis_db']}" + +rails_env = node.chef_environment == "development" ? "development" : "production" +deploy_env = { + # FIXME: /usr/bin was missing from PATH when running `yarn install` + "PATH" => "#{ruby_path}/bin:/usr/bin:$PATH", + "HOME" => mastodon_path, + "RAILS_ENV" => rails_env, + "NODE_ENV" => rails_env, + "COREPACK_ENABLE_DOWNLOAD_PROMPT" => "0" +} + +# Skip the build while the checked-out revision is unchanged +build_uptodate = "test -f #{mastodon_path}/tmp/built-revision && " \ + "test \"$(cat #{mastodon_path}/tmp/built-revision)\" = \"$(git -C #{mastodon_path} rev-parse HEAD)\"" + +git mastodon_path do + user mastodon_user + group mastodon_user + + repository node["kosmos-mastodon"]["repo"] + revision node["kosmos-mastodon"]["revision"] +end + +credentials = data_bag_item('credentials', 'mastodon') + +ldap_config = { + host: "ldap.kosmos.local", + port: 389, + method: "plain", + base: "ou=kosmos.org,cn=users,dc=kosmos,dc=org", + bind_dn: credentials["ldap_bind_dn"], + password: credentials["ldap_password"], + uid: "cn", + mail: "mail", + search_filter: "(&(|(cn=%{email})(mail=%{email}))(serviceEnabled=mastodon))", + uid_conversion_enabled: "true", + uid_conversion_search: "-", + uid_conversion_replace: "_" +} + +template "#{mastodon_path}/.env.#{rails_env}" do + source "env.erb" + mode "0640" + owner mastodon_user + group mastodon_user + sensitive true + variables redis_url: redis_url, + domain: node["kosmos-mastodon"]["domain"], + alternate_domains: node["kosmos-mastodon"]["alternate_domains"], + active_record_encryption_deterministic_key: credentials["active_record_encryption_deterministic_key"], + active_record_encryption_key_derivation_salt: credentials["active_record_encryption_key_derivation_salt"], + active_record_encryption_primary_key: credentials["active_record_encryption_primary_key"], + paperclip_secret: credentials['paperclip_secret'], + secret_key_base: credentials['secret_key_base'], + ldap: ldap_config, + smtp_login: credentials['smtp_user_name'], + smtp_password: credentials['smtp_password'], + smtp_from_address: "mail@#{node['kosmos-mastodon']['domain']}", + s3_endpoint: node["kosmos-mastodon"]["s3_endpoint"], + s3_region: node["kosmos-mastodon"]["s3_region"], + s3_bucket: node["kosmos-mastodon"]["s3_bucket"], + s3_alias_host: node["kosmos-mastodon"]["s3_alias_host"], + aws_access_key_id: credentials['s3_key_id'], + aws_secret_access_key: credentials['s3_secret_key'], + vapid_private_key: credentials['vapid_private_key'], + vapid_public_key: credentials['vapid_public_key'], + db_pass: postgresql_credentials['mastodon_user_password'], + db_host: "pg.kosmos.local", + sso_account_sign_up_url: node["kosmos-mastodon"]["sso_account_sign_up_url"], + sso_account_reset_password_url: node["kosmos-mastodon"]["sso_account_reset_password_url"], + sso_account_resend_confirmation_url: node["kosmos-mastodon"]["sso_account_resend_confirmation_url"], + default_locale: node["kosmos-mastodon"]["default_locale"], + force_default_locale: node["kosmos-mastodon"]["force_default_locale"], + disable_email_subscriptions: node["kosmos-mastodon"]["disable_email_subscriptions"], + allowed_private_addresses: node["kosmos-mastodon"]["allowed_private_addresses"], + libre_translate_endpoint: node["kosmos-mastodon"]["libre_translate_endpoint"] + notifies :run, "execute[restart mastodon services]", :delayed if node["kosmos-mastodon"]["deploy"] +end + +execute "bundle install" do + environment deploy_env.merge("BUNDLE_BUILD__CHARLOCK_HOLMES" => "--with-cxxflags=-std=c++17") + user mastodon_user + cwd mastodon_path + command "bundle install --without development,test --deployment" + not_if build_uptodate +end + +execute "yarn install" do + environment deploy_env + user mastodon_user + cwd mastodon_path + command "yarn install --immutable" + not_if build_uptodate +end + +execute "rake assets:precompile" do + environment deploy_env + user mastodon_user + group mastodon_user + cwd mastodon_path + command "bundle exec rake assets:precompile" + not_if build_uptodate + notifies :create, "file[#{mastodon_path}/tmp/built-revision]", :immediately +end + +file "#{mastodon_path}/tmp/built-revision" do + content lazy { `git -C #{mastodon_path} rev-parse HEAD`.strip } + owner mastodon_user + group mastodon_user + mode "0644" + action :nothing +end diff --git a/site-cookbooks/kosmos-mastodon/recipes/default.rb b/site-cookbooks/kosmos-mastodon/recipes/default.rb index c96e242..9401dd8 100644 --- a/site-cookbooks/kosmos-mastodon/recipes/default.rb +++ b/site-cookbooks/kosmos-mastodon/recipes/default.rb @@ -5,325 +5,8 @@ include_recipe "kosmos-mastodon::dependencies" -# The rest is the actual Mastodon deployment. Skip it when only the runtime -# dependencies should be installed (e.g. to pre-stage a new VM). -return unless node["kosmos-mastodon"]["deploy"] +# Check out and build the application without touching the database. +include_recipe "kosmos-mastodon::build" if node["kosmos-mastodon"]["build"] || node["kosmos-mastodon"]["deploy"] -require 'uri' - -postgresql_credentials = data_bag_item('credentials', 'postgresql') - -mastodon_path = node["kosmos-mastodon"]["directory"] -mastodon_user = "mastodon" - -bind_ip = if node.chef_environment == "production" - node["knife_zero"]["host"] - else - node["kosmos-mastodon"]["bind_ip"] - end - -ruby_version = node["kosmos-mastodon"]["ruby_version"] -ruby_path = "/opt/ruby_build/builds/#{ruby_version}" -bundle_path = "#{ruby_path}/bin/bundle" - -# External Redis cluster (see the kosmos_redis cookbook) -redis_host = search(:node, "role:#{node['kosmos-mastodon']['redis_server_role']}").first&.dig("knife_zero", "host") - -if redis_host.nil? - Chef::Log.fatal("No node found with '#{node['kosmos-mastodon']['redis_server_role']}' role. Stopping here.") - return -end - -redis_password = URI.encode_www_form_component(data_bag_item('credentials', 'redis')['password']) -redis_url = "redis://:#{redis_password}@#{redis_host}:#{node['kosmos-mastodon']['redis_port']}/#{node['kosmos-mastodon']['redis_db']}" - -execute "systemctl daemon-reload" do - command "systemctl daemon-reload" - action :nothing -end - -# mastodon-web service -# -template "/lib/systemd/system/mastodon-web.service" do - source "mastodon-web.systemd.service.erb" - variables user: mastodon_user, - app_dir: mastodon_path, - bind: bind_ip, - port: node["kosmos-mastodon"]["app_port"], - bundle_path: bundle_path - notifies :run, "execute[systemctl daemon-reload]", :immediately - notifies :restart, "service[mastodon-web]", :delayed -end - -# mastodon-sidekiq service -# -template "/lib/systemd/system/mastodon-sidekiq.service" do - source "mastodon-sidekiq.systemd.service.erb" - variables user: mastodon_user, - app_dir: mastodon_path, - bundle_path: bundle_path, - sidekiq_threads: node["kosmos-mastodon"]["sidekiq_threads"] - notifies :run, "execute[systemctl daemon-reload]", :immediately - notifies :restart, "service[mastodon-sidekiq]", :delayed -end - -# mastodon-sidekiq-scheduler service -# -template "/lib/systemd/system/mastodon-sidekiq-scheduler.service" do - source "mastodon-sidekiq-scheduler.systemd.service.erb" - variables user: mastodon_user, - app_dir: mastodon_path, - bundle_path: bundle_path, - sidekiq_threads: 1 - notifies :run, "execute[systemctl daemon-reload]", :immediately - notifies :restart, "service[mastodon-sidekiq-scheduler]", :delayed -end - -# mastodon-streaming service -# -template "/lib/systemd/system/mastodon-streaming.service" do - source "mastodon-streaming.systemd.service.erb" - variables user: mastodon_user, - app_dir: mastodon_path, - bind: bind_ip, - port: node["kosmos-mastodon"]["streaming_port"] - notifies :run, "execute[systemctl daemon-reload]", :immediately - notifies :restart, "service[mastodon-streaming]", :delayed -end - -rails_env = node.chef_environment == "development" ? "development" : "production" -deploy_env = { - # FIXME: /usr/bin was missing from PATH when running `yarn install` - "PATH" => "#{ruby_path}/bin:/usr/bin:$PATH", - "HOME" => mastodon_path, - "RAILS_ENV" => rails_env, - "NODE_ENV" => rails_env, - "COREPACK_ENABLE_DOWNLOAD_PROMPT" => "0" -} - -git mastodon_path do - user mastodon_user - group mastodon_user - - repository node["kosmos-mastodon"]["repo"] - revision node["kosmos-mastodon"]["revision"] - # Restart services (and run post-deployment migrations) on deployments - notifies :run, "execute[restart mastodon services]", :delayed -end - -execute "restart mastodon services" do - command "systemctl restart mastodon-web mastodon-sidekiq mastodon-sidekiq-scheduler mastodon-streaming" - action :nothing - notifies :run, "execute[rake db:migrate (post-deployment)]", :immediately -end - -credentials = data_bag_item('credentials', 'mastodon') - -ldap_config = { - host: "ldap.kosmos.local", - port: 389, - method: "plain", - base: "ou=kosmos.org,cn=users,dc=kosmos,dc=org", - bind_dn: credentials["ldap_bind_dn"], - password: credentials["ldap_password"], - uid: "cn", - mail: "mail", - search_filter: "(&(|(cn=%{email})(mail=%{email}))(serviceEnabled=mastodon))", - uid_conversion_enabled: "true", - uid_conversion_search: "-", - uid_conversion_replace: "_" -} - -template "#{mastodon_path}/.env.#{rails_env}" do - source "env.erb" - mode "0640" - owner mastodon_user - group mastodon_user - sensitive true - variables redis_url: redis_url, - domain: node["kosmos-mastodon"]["domain"], - alternate_domains: node["kosmos-mastodon"]["alternate_domains"], - active_record_encryption_deterministic_key: credentials["active_record_encryption_deterministic_key"], - active_record_encryption_key_derivation_salt: credentials["active_record_encryption_key_derivation_salt"], - active_record_encryption_primary_key: credentials["active_record_encryption_primary_key"], - paperclip_secret: credentials['paperclip_secret'], - secret_key_base: credentials['secret_key_base'], - ldap: ldap_config, - smtp_login: credentials['smtp_user_name'], - smtp_password: credentials['smtp_password'], - smtp_from_address: "mail@#{node['kosmos-mastodon']['domain']}", - s3_endpoint: node["kosmos-mastodon"]["s3_endpoint"], - s3_region: node["kosmos-mastodon"]["s3_region"], - s3_bucket: node["kosmos-mastodon"]["s3_bucket"], - s3_alias_host: node["kosmos-mastodon"]["s3_alias_host"], - aws_access_key_id: credentials['s3_key_id'], - aws_secret_access_key: credentials['s3_secret_key'], - vapid_private_key: credentials['vapid_private_key'], - vapid_public_key: credentials['vapid_public_key'], - db_pass: postgresql_credentials['mastodon_user_password'], - db_host: "pg.kosmos.local", - sso_account_sign_up_url: node["kosmos-mastodon"]["sso_account_sign_up_url"], - sso_account_reset_password_url: node["kosmos-mastodon"]["sso_account_reset_password_url"], - sso_account_resend_confirmation_url: node["kosmos-mastodon"]["sso_account_resend_confirmation_url"], - default_locale: node["kosmos-mastodon"]["default_locale"], - force_default_locale: node["kosmos-mastodon"]["force_default_locale"], - disable_email_subscriptions: node["kosmos-mastodon"]["disable_email_subscriptions"], - allowed_private_addresses: node["kosmos-mastodon"]["allowed_private_addresses"], - libre_translate_endpoint: node["kosmos-mastodon"]["libre_translate_endpoint"] - notifies :run, "execute[restart mastodon services]", :delayed -end - -execute "bundle install" do - environment deploy_env.merge("BUNDLE_BUILD__CHARLOCK_HOLMES" => "--with-cxxflags=-std=c++17") - user mastodon_user - cwd mastodon_path - command "bundle install --without development,test --deployment" -end - -execute "yarn install" do - environment deploy_env - user mastodon_user - cwd mastodon_path - command "yarn install --immutable" -end - -execute "rake assets:precompile" do - environment deploy_env - user mastodon_user - group mastodon_user - cwd mastodon_path - command "bundle exec rake assets:precompile" -end - -# Mastodon 4.4+ splits migrations into pre- and post-deployment phases. -# Pre-deployment migrations must run before the services are (re)started. -execute "rake db:migrate (pre-deployment)" do - environment deploy_env.merge("SKIP_POST_DEPLOYMENT_MIGRATIONS" => "true") - user mastodon_user - group mastodon_user - cwd mastodon_path - command "bundle exec rake db:migrate" - timeout 21_600 -end - -execute "rake db:migrate (post-deployment)" do - environment deploy_env - user mastodon_user - group mastodon_user - cwd mastodon_path - command "bundle exec rake db:migrate" - timeout 21_600 - action :nothing - notifies :run, "execute[tootctl search deploy (create indices)]", :immediately -end - -# Create or upgrade the Elasticsearch indices and mappings without importing -# data, so that search does not fail on a missing index. The (potentially very -# long) import is deferred to a systemd unit started in the background below. -execute "tootctl search deploy (create indices)" do - environment deploy_env - user mastodon_user - group mastodon_user - cwd mastodon_path - command "#{bundle_path} exec bin/tootctl search deploy --no-import" - timeout 3_600 - action :nothing - notifies :run, "execute[start mastodon search deploy]", :immediately -end - -execute "start mastodon search deploy" do - command "systemctl start --no-block mastodon-search-deploy.service" - action :nothing -end - -service "mastodon-web" do - action [:enable, :start] -end - -service "mastodon-sidekiq" do - action [:enable, :start] -end - -service "mastodon-sidekiq-scheduler" do - action [:enable, :start] -end - -service "mastodon-streaming" do - action [:enable, :start] -end - -# -# Delete cached remote media older than 30 days -# Will be re-fetched if necessary -# - -systemd_unit 'mastodon-delete-old-media-cache.service' do - content({ - Unit: { - Description: 'Delete old Mastodon media cache' - }, - Service: { - Type: "oneshot", - WorkingDirectory: mastodon_path, - Environment: "RAILS_ENV=#{rails_env}", - ExecStart: "#{bundle_path} exec bin/tootctl media remove --days 30", - } - }) - triggers_reload true - action [:create] -end - -systemd_unit 'mastodon-delete-old-media-cache.timer' do - content({ - Unit: { - Description: 'Delete old Mastodon media cache' - }, - Timer: { - OnCalendar: '*-*-* 00:00:00', - Persistent: 'true' - }, - Install: { - WantedBy: 'timer.target' - } - }) - triggers_reload true - action [:create, :enable, :start] -end - -# -# Populate the Elasticsearch indices in the background. The indices and -# mappings are created synchronously by the recipe above; this unit only does -# the (potentially very long) import, so it is started without blocking. -# - -systemd_unit 'mastodon-search-deploy.service' do - content({ - Unit: { - Description: 'Populate the Mastodon search index' - }, - Service: { - Type: "oneshot", - User: mastodon_user, - WorkingDirectory: mastodon_path, - Environment: "RAILS_ENV=#{rails_env}", - ExecStart: "#{bundle_path} exec bin/tootctl search deploy", - TimeoutStartSec: "21600", - } - }) - triggers_reload true - action [:create] -end - -firewall_rule "mastodon_app" do - port node['kosmos-mastodon']['app_port'] - source "10.1.1.0/24" - protocol :tcp - command :allow -end - -firewall_rule 'mastodon_streaming' do - port node['kosmos-mastodon']['streaming_port'] - source "10.1.1.0/24" - protocol :tcp - command :allow -end +# Run migrations and manage the services. +include_recipe "kosmos-mastodon::deploy" if node["kosmos-mastodon"]["deploy"] diff --git a/site-cookbooks/kosmos-mastodon/recipes/deploy.rb b/site-cookbooks/kosmos-mastodon/recipes/deploy.rb new file mode 100644 index 0000000..b0d4fed --- /dev/null +++ b/site-cookbooks/kosmos-mastodon/recipes/deploy.rb @@ -0,0 +1,240 @@ +# +# Cookbook Name:: kosmos-mastodon +# Recipe:: deploy +# +# Runs database migrations and manages the services. Requires the application +# to have been checked out and built by kosmos-mastodon::build. Migrations and +# the service restart run once per checked-out revision. +# + +mastodon_path = node["kosmos-mastodon"]["directory"] +mastodon_user = "mastodon" + +bind_ip = if node.chef_environment == "production" + node["knife_zero"]["host"] + else + node["kosmos-mastodon"]["bind_ip"] + end + +ruby_version = node["kosmos-mastodon"]["ruby_version"] +ruby_path = "/opt/ruby_build/builds/#{ruby_version}" +bundle_path = "#{ruby_path}/bin/bundle" + +rails_env = node.chef_environment == "development" ? "development" : "production" +deploy_env = { + # FIXME: /usr/bin was missing from PATH when running `yarn install` + "PATH" => "#{ruby_path}/bin:/usr/bin:$PATH", + "HOME" => mastodon_path, + "RAILS_ENV" => rails_env, + "NODE_ENV" => rails_env, + "COREPACK_ENABLE_DOWNLOAD_PROMPT" => "0" +} + +# Run migrations, restart services and (re)build the search index once per +# checked-out revision, regardless of whether the code was pre-built. +deploy_uptodate = "test -f #{mastodon_path}/tmp/deployed-revision && " \ + "test \"$(cat #{mastodon_path}/tmp/deployed-revision)\" = \"$(git -C #{mastodon_path} rev-parse HEAD)\"" + +execute "systemctl daemon-reload" do + command "systemctl daemon-reload" + action :nothing +end + +# mastodon-web service +# +template "/lib/systemd/system/mastodon-web.service" do + source "mastodon-web.systemd.service.erb" + variables user: mastodon_user, + app_dir: mastodon_path, + bind: bind_ip, + port: node["kosmos-mastodon"]["app_port"], + bundle_path: bundle_path + notifies :run, "execute[systemctl daemon-reload]", :immediately + notifies :restart, "service[mastodon-web]", :delayed +end + +# mastodon-sidekiq service +# +template "/lib/systemd/system/mastodon-sidekiq.service" do + source "mastodon-sidekiq.systemd.service.erb" + variables user: mastodon_user, + app_dir: mastodon_path, + bundle_path: bundle_path, + sidekiq_threads: node["kosmos-mastodon"]["sidekiq_threads"] + notifies :run, "execute[systemctl daemon-reload]", :immediately + notifies :restart, "service[mastodon-sidekiq]", :delayed +end + +# mastodon-sidekiq-scheduler service +# +template "/lib/systemd/system/mastodon-sidekiq-scheduler.service" do + source "mastodon-sidekiq-scheduler.systemd.service.erb" + variables user: mastodon_user, + app_dir: mastodon_path, + bundle_path: bundle_path, + sidekiq_threads: 1 + notifies :run, "execute[systemctl daemon-reload]", :immediately + notifies :restart, "service[mastodon-sidekiq-scheduler]", :delayed +end + +# mastodon-streaming service +# +template "/lib/systemd/system/mastodon-streaming.service" do + source "mastodon-streaming.systemd.service.erb" + variables user: mastodon_user, + app_dir: mastodon_path, + bind: bind_ip, + port: node["kosmos-mastodon"]["streaming_port"] + notifies :run, "execute[systemctl daemon-reload]", :immediately + notifies :restart, "service[mastodon-streaming]", :delayed +end + +execute "restart mastodon services" do + command "systemctl restart mastodon-web mastodon-sidekiq mastodon-sidekiq-scheduler mastodon-streaming" + action :nothing +end + +# Mastodon 4.4+ splits migrations into pre- and post-deployment phases. +# Pre-deployment migrations must run before the services are (re)started. +execute "rake db:migrate (pre-deployment)" do + environment deploy_env.merge("SKIP_POST_DEPLOYMENT_MIGRATIONS" => "true") + user mastodon_user + group mastodon_user + cwd mastodon_path + command "bundle exec rake db:migrate" + timeout 21_600 + not_if deploy_uptodate + notifies :run, "execute[restart mastodon services]", :immediately + notifies :run, "execute[rake db:migrate (post-deployment)]", :immediately +end + +execute "rake db:migrate (post-deployment)" do + environment deploy_env + user mastodon_user + group mastodon_user + cwd mastodon_path + command "bundle exec rake db:migrate" + timeout 21_600 + action :nothing + notifies :run, "execute[tootctl search deploy (create indices)]", :immediately +end + +# Create or upgrade the Elasticsearch indices and mappings without importing +# data, so that search does not fail on a missing index. The (potentially very +# long) import is deferred to a systemd unit started in the background below. +execute "tootctl search deploy (create indices)" do + environment deploy_env + user mastodon_user + group mastodon_user + cwd mastodon_path + command "#{bundle_path} exec bin/tootctl search deploy --no-import" + timeout 3_600 + action :nothing + notifies :run, "execute[start mastodon search deploy]", :immediately + notifies :create, "file[#{mastodon_path}/tmp/deployed-revision]", :immediately +end + +execute "start mastodon search deploy" do + command "systemctl start --no-block mastodon-search-deploy.service" + action :nothing +end + +file "#{mastodon_path}/tmp/deployed-revision" do + content lazy { `git -C #{mastodon_path} rev-parse HEAD`.strip } + owner mastodon_user + group mastodon_user + mode "0644" + action :nothing +end + +service "mastodon-web" do + action [:enable, :start] +end + +service "mastodon-sidekiq" do + action [:enable, :start] +end + +service "mastodon-sidekiq-scheduler" do + action [:enable, :start] +end + +service "mastodon-streaming" do + action [:enable, :start] +end + +# +# Delete cached remote media older than 30 days +# Will be re-fetched if necessary +# + +systemd_unit 'mastodon-delete-old-media-cache.service' do + content({ + Unit: { + Description: 'Delete old Mastodon media cache' + }, + Service: { + Type: "oneshot", + WorkingDirectory: mastodon_path, + Environment: "RAILS_ENV=#{rails_env}", + ExecStart: "#{bundle_path} exec bin/tootctl media remove --days 30", + } + }) + triggers_reload true + action [:create] +end + +systemd_unit 'mastodon-delete-old-media-cache.timer' do + content({ + Unit: { + Description: 'Delete old Mastodon media cache' + }, + Timer: { + OnCalendar: '*-*-* 00:00:00', + Persistent: 'true' + }, + Install: { + WantedBy: 'timer.target' + } + }) + triggers_reload true + action [:create, :enable, :start] +end + +# +# Populate the Elasticsearch indices in the background. The indices and +# mappings are created synchronously by the recipe above; this unit only does +# the (potentially very long) import, so it is started without blocking. +# + +systemd_unit 'mastodon-search-deploy.service' do + content({ + Unit: { + Description: 'Populate the Mastodon search index' + }, + Service: { + Type: "oneshot", + User: mastodon_user, + WorkingDirectory: mastodon_path, + Environment: "RAILS_ENV=#{rails_env}", + ExecStart: "#{bundle_path} exec bin/tootctl search deploy", + TimeoutStartSec: "21600", + } + }) + triggers_reload true + action [:create] +end + +firewall_rule "mastodon_app" do + port node['kosmos-mastodon']['app_port'] + source "10.1.1.0/24" + protocol :tcp + command :allow +end + +firewall_rule 'mastodon_streaming' do + port node['kosmos-mastodon']['streaming_port'] + source "10.1.1.0/24" + protocol :tcp + command :allow +end