1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Mix.Tasks.Pleroma.Instance do
9 @shortdoc "Manages Pleroma instance"
11 Manages Pleroma instance.
13 ## Generate a new instance config.
15 mix pleroma.instance gen [OPTION...]
17 If any options are left unspecified, you will be prompted interactively
21 - `-f`, `--force` - overwrite any output files
22 - `-o PATH`, `--output PATH` - the output file for the generated configuration
23 - `--output-psql PATH` - the output file for the generated PostgreSQL setup
24 - `--domain DOMAIN` - the domain of your instance
25 - `--instance-name INSTANCE_NAME` - the name of your instance
26 - `--admin-email ADMIN_EMAIL` - the email address of the instance admin
27 - `--notify-email NOTIFY_EMAIL` - email address for notifications
28 - `--dbhost HOSTNAME` - the hostname of the PostgreSQL database to use
29 - `--dbname DBNAME` - the name of the database to use
30 - `--dbuser DBUSER` - the user (aka role) to use for the database connection
31 - `--dbpass DBPASS` - the password to use for the database connection
32 - `--rum Y/N` - Whether to enable RUM indexes
33 - `--indexable Y/N` - Allow/disallow indexing site by search engines
34 - `--db-configurable Y/N` - Allow/disallow configuring instance from admin part
35 - `--uploads-dir` - the directory uploads go in when using a local uploader
36 - `--static-dir` - the directory custom public files should be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)
37 - `--listen-ip` - the ip the app should listen to, defaults to 127.0.0.1
38 - `--listen-port` - the port the app should listen to, defaults to 4000
41 def run(["gen" | rest]) do
50 instance_name: :string,
52 notify_email: :string,
59 db_configurable: :string,
72 [config_path, psql_path] = [
73 Keyword.get(options, :output, "config/generated_config.exs"),
74 Keyword.get(options, :output_psql, "config/setup_db.psql")
77 will_overwrite = Enum.filter(paths, &File.exists?/1)
78 proceed? = Enum.empty?(will_overwrite) or Keyword.get(options, :force, false)
86 "What domain will your instance use? (e.g pleroma.soykaf.com)"
95 "What is the name of your instance? (e.g. Pleroma/Soykaf)"
98 email = get_option(options, :admin_email, "What is your admin email address?")
104 "What email address do you want to use for sending email notifications?",
112 "Do you want search engines to index your site? (y/n)",
120 "Do you want to store the configuration in the database (allows controlling it from admin-fe)? (y/n)",
124 dbhost = get_option(options, :dbhost, "What is the hostname of your database?", "localhost")
126 dbname = get_option(options, :dbname, "What is the name of your database?", "pleroma")
132 "What is the user used to connect to your database?",
140 "What is the password used to connect to your database?",
141 :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64),
149 "Would you like to use RUM indices?",
157 "What port will the app listen to (leave it if you are using the default setup with nginx)?",
165 "What ip will the app listen to (leave it if you are using the default setup with nginx)?",
173 "What directory should media uploads go in (when using the local uploader)?",
174 Pleroma.Config.get([Pleroma.Uploaders.Local, :uploads])
181 "What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)?",
182 Pleroma.Config.get([:instance, :static_dir])
185 secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
186 jwt_secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
187 signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
188 {web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
189 template_dir = Application.app_dir(:pleroma, "priv") <> "/templates"
193 template_dir <> "/sample_config.eex",
197 notify_email: notify_email,
204 jwt_secret: jwt_secret,
205 signing_salt: signing_salt,
206 web_push_public_key: Base.url_encode64(web_push_public_key, padding: false),
207 web_push_private_key: Base.url_encode64(web_push_private_key, padding: false),
208 db_configurable?: db_configurable?,
209 static_dir: static_dir,
210 uploads_dir: uploads_dir,
211 rum_enabled: rum_enabled,
212 listen_ip: listen_ip,
213 listen_port: listen_port
218 template_dir <> "/sample_psql.eex",
222 rum_enabled: rum_enabled
225 shell_info("Writing config to #{config_path}.")
227 File.write(config_path, result_config)
228 shell_info("Writing the postgres script to #{psql_path}.")
229 File.write(psql_path, result_psql)
231 write_robots_txt(indexable, template_dir)
234 "\n All files successfully written! Refer to the installation instructions for your platform for next steps"
238 "The task would have overwritten the following files:\n" <>
239 (Enum.map(paths, &"- #{&1}\n") |> Enum.join("")) <>
240 "Rerun with `--force` to overwrite them."
245 defp write_robots_txt(indexable, template_dir) do
248 template_dir <> "/robots_txt.eex",
252 static_dir = Pleroma.Config.get([:instance, :static_dir], "instance/static/")
254 unless File.exists?(static_dir) do
255 File.mkdir_p!(static_dir)
258 robots_txt_path = Path.join(static_dir, "robots.txt")
260 if File.exists?(robots_txt_path) do
261 File.cp!(robots_txt_path, "#{robots_txt_path}.bak")
262 shell_info("Backing up existing robots.txt to #{robots_txt_path}.bak")
265 File.write(robots_txt_path, robots_txt)
266 shell_info("Writing #{robots_txt_path}.")