1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Mix.Tasks.Pleroma.Instance do
11 @shortdoc "Manages Pleroma instance"
12 @moduledoc File.read!("docs/docs/administration/CLI_tasks/instance.md")
14 def run(["gen" | rest]) do
23 instance_name: :string,
25 notify_email: :string,
32 db_configurable: :string,
37 strip_uploads: :string,
38 anonymize_uploads: :string,
39 dedupe_uploads: :string
48 [config_path, psql_path] = [
49 Keyword.get(options, :output, "config/generated_config.exs"),
50 Keyword.get(options, :output_psql, "config/setup_db.psql")
53 will_overwrite = Enum.filter(paths, &File.exists?/1)
54 proceed? = Enum.empty?(will_overwrite) or Keyword.get(options, :force, false)
62 "What domain will your instance use? (e.g akkoma.example.com)"
71 "What is the name of your instance? (e.g. The Corndog Emporium)",
75 email = get_option(options, :admin_email, "What is your admin email address?")
81 "What email address do you want to use for sending email notifications?",
89 "Do you want search engines to index your site? (y/n)",
97 "Do you want to store the configuration in the database (allows controlling it from admin-fe)? (y/n)",
101 dbhost = get_option(options, :dbhost, "What is the hostname of your database?", "localhost")
103 dbname = get_option(options, :dbname, "What is the name of your database?", "akkoma")
109 "What is the user used to connect to your database?",
117 "What is the password used to connect to your database?",
118 :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64),
126 "Would you like to use RUM indices?",
134 "What port will the app listen to (leave it if you are using the default setup with nginx)?",
142 "What ip will the app listen to (leave it if you are using the default setup with nginx)?",
150 "What directory should media uploads go in (when using the local uploader)?",
151 Config.get([Pleroma.Uploaders.Local, :uploads])
159 "What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)?",
160 Config.get([:instance, :static_dir])
164 {strip_uploads_message, strip_uploads_default} =
165 if Pleroma.Utils.command_available?("exiftool") do
166 {"Do you want to strip location (GPS) data from uploaded images? This requires exiftool, it was detected as installed. (y/n)",
169 {"Do you want to strip location (GPS) data from uploaded images? This requires exiftool, it was detected as not installed, please install it if you answer yes. (y/n)",
177 strip_uploads_message,
178 strip_uploads_default
185 "Do you want to anonymize the filenames of uploads? (y/n)",
193 "Do you want to deduplicate uploaded files? (y/n)",
197 Config.put([:instance, :static_dir], static_dir)
199 secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
200 jwt_secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
201 signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
202 lv_signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
203 {web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
204 template_dir = Application.app_dir(:pleroma, "priv") <> "/templates"
208 template_dir <> "/sample_config.eex",
212 notify_email: notify_email,
219 jwt_secret: jwt_secret,
220 signing_salt: signing_salt,
221 lv_signing_salt: lv_signing_salt,
222 web_push_public_key: Base.url_encode64(web_push_public_key, padding: false),
223 web_push_private_key: Base.url_encode64(web_push_private_key, padding: false),
224 db_configurable?: db_configurable?,
225 static_dir: static_dir,
226 uploads_dir: uploads_dir,
227 rum_enabled: rum_enabled,
228 listen_ip: listen_ip,
229 listen_port: listen_port,
232 strip: strip_uploads,
233 anonymize: anonymize_uploads,
234 dedupe: dedupe_uploads
240 template_dir <> "/sample_psql.eex",
244 rum_enabled: rum_enabled
247 config_dir = Path.dirname(config_path)
248 psql_dir = Path.dirname(psql_path)
251 [config_dir, psql_dir, static_dir, uploads_dir]
252 |> Enum.reject(&File.exists?/1)
254 for dir <- to_create do
258 shell_info("Writing config to #{config_path}.")
260 File.write(config_path, result_config)
261 shell_info("Writing the postgres script to #{psql_path}.")
262 File.write(psql_path, result_psql)
264 write_robots_txt(static_dir, indexable, template_dir)
267 "\n All files successfully written! Refer to the installation instructions for your platform for next steps."
270 if db_configurable? do
272 " Please transfer your config to the database after running database migrations. Refer to \"Transfering the config to/from the database\" section of the docs for more information."
277 "The task would have overwritten the following files:\n" <>
278 (Enum.map(will_overwrite, &"- #{&1}\n") |> Enum.join("")) <>
279 "Rerun with `--force` to overwrite them."
284 defp write_robots_txt(static_dir, indexable, template_dir) do
287 template_dir <> "/robots_txt.eex",
291 robots_txt_path = Path.join(static_dir, "robots.txt")
293 if File.exists?(robots_txt_path) do
294 File.cp!(robots_txt_path, "#{robots_txt_path}.bak")
295 shell_info("Backing up existing robots.txt to #{robots_txt_path}.bak")
298 File.write(robots_txt_path, robots_txt)
299 shell_info("Writing #{robots_txt_path}.")
302 defp upload_filters(filters) when is_map(filters) do
305 [Pleroma.Upload.Filter.Exiftool]
311 if filters.anonymize do
312 enabled_filters ++ [Pleroma.Upload.Filter.AnonymizeFilename]
319 enabled_filters ++ [Pleroma.Upload.Filter.Dedupe]