2018-12-23 20:05:55 +00:00
# Pleroma: A lightweight social networking server
2023-01-02 20:38:50 +00:00
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
2018-12-23 20:05:55 +00:00
# SPDX-License-Identifier: AGPL-3.0-only
2018-12-02 18:18:06 +00:00
defmodule Mix.Tasks.Pleroma.Instance do
2018-06-29 00:24:51 +00:00
use Mix.Task
2019-06-19 23:05:19 +00:00
import Mix.Pleroma
2018-06-29 00:24:51 +00:00
2020-02-24 19:52:38 +00:00
alias Pleroma.Config
2018-12-02 18:18:06 +00:00
@shortdoc " Manages Pleroma instance "
2019-10-03 10:59:49 +00:00
@moduledoc File . read! ( " docs/administration/CLI_tasks/instance.md " )
2018-06-29 00:24:51 +00:00
2018-12-04 18:00:45 +00:00
def run ( [ " gen " | rest ] ) do
2018-06-29 00:24:51 +00:00
{ options , [ ] , [ ] } =
OptionParser . parse (
rest ,
strict : [
force : :boolean ,
output : :string ,
output_psql : :string ,
domain : :string ,
instance_name : :string ,
admin_email : :string ,
2019-04-10 10:57:41 +00:00
notify_email : :string ,
2018-06-29 00:24:51 +00:00
dbhost : :string ,
dbname : :string ,
dbuser : :string ,
2019-04-10 10:57:41 +00:00
dbpass : :string ,
2019-06-22 09:54:16 +00:00
rum : :string ,
2019-06-14 15:45:05 +00:00
indexable : :string ,
2019-06-20 00:59:16 +00:00
db_configurable : :string ,
uploads_dir : :string ,
2019-07-09 19:57:41 +00:00
static_dir : :string ,
listen_ip : :string ,
2020-10-12 16:18:39 +00:00
listen_port : :string ,
2022-02-20 12:46:29 +00:00
strip_uploads_location : :string ,
2022-02-20 11:59:42 +00:00
read_uploads_description : :string ,
2020-10-12 16:18:39 +00:00
anonymize_uploads : :string ,
2020-11-07 19:09:28 +00:00
dedupe_uploads : :string
2018-06-29 00:24:51 +00:00
] ,
aliases : [
o : :output ,
f : :force
]
)
paths =
[ config_path , psql_path ] = [
Keyword . get ( options , :output , " config/generated_config.exs " ) ,
Keyword . get ( options , :output_psql , " config/setup_db.psql " )
]
will_overwrite = Enum . filter ( paths , & File . exists? / 1 )
proceed? = Enum . empty? ( will_overwrite ) or Keyword . get ( options , :force , false )
2019-04-10 10:57:41 +00:00
if proceed? do
2018-12-15 10:00:54 +00:00
[ domain , port | _ ] =
String . split (
2019-06-19 23:05:19 +00:00
get_option (
2018-12-15 10:00:54 +00:00
options ,
:domain ,
" What domain will your instance use? (e.g pleroma.soykaf.com) "
) ,
" : "
) ++ [ 443 ]
2018-06-29 00:24:51 +00:00
name =
2019-06-19 23:05:19 +00:00
get_option (
2018-12-06 17:01:28 +00:00
options ,
2018-12-29 11:43:54 +00:00
:instance_name ,
2020-02-25 21:32:34 +00:00
" What is the name of your instance? (e.g. The Corndog Emporium) " ,
2020-02-25 18:59:37 +00:00
domain
2018-12-06 17:01:28 +00:00
)
2018-06-29 00:24:51 +00:00
2019-06-19 23:05:19 +00:00
email = get_option ( options , :admin_email , " What is your admin email address? " )
2018-12-02 19:04:33 +00:00
2019-04-10 10:57:41 +00:00
notify_email =
2019-06-19 23:05:19 +00:00
get_option (
2019-04-10 10:57:41 +00:00
options ,
:notify_email ,
" What email address do you want to use for sending email notifications? " ,
email
)
2019-04-02 19:09:16 +00:00
indexable =
2019-06-19 23:05:19 +00:00
get_option (
2019-04-02 19:09:16 +00:00
options ,
:indexable ,
" Do you want search engines to index your site? (y/n) " ,
" y "
) === " y "
2019-06-14 15:45:05 +00:00
db_configurable? =
2019-06-19 23:05:19 +00:00
get_option (
2019-06-14 15:45:05 +00:00
options ,
:db_configurable ,
2019-06-20 00:59:16 +00:00
" Do you want to store the configuration in the database (allows controlling it from admin-fe)? (y/n) " ,
2019-06-21 03:42:04 +00:00
" n "
2019-06-14 15:45:05 +00:00
) === " y "
2018-12-02 19:04:33 +00:00
2019-06-19 23:05:19 +00:00
dbhost = get_option ( options , :dbhost , " What is the hostname of your database? " , " localhost " )
2018-12-02 19:04:33 +00:00
2019-06-21 03:42:04 +00:00
dbname = get_option ( options , :dbname , " What is the name of your database? " , " pleroma " )
2018-06-29 00:24:51 +00:00
dbuser =
2019-06-19 23:05:19 +00:00
get_option (
2018-12-02 19:04:33 +00:00
options ,
:dbuser ,
" What is the user used to connect to your database? " ,
" pleroma "
)
2018-06-29 00:24:51 +00:00
dbpass =
2019-06-19 23:05:19 +00:00
get_option (
2018-12-02 19:04:33 +00:00
options ,
:dbpass ,
" What is the password used to connect to your database? " ,
:crypto . strong_rand_bytes ( 64 ) |> Base . encode64 ( ) |> binary_part ( 0 , 64 ) ,
" autogenerated "
)
2018-06-29 00:24:51 +00:00
2019-06-22 09:54:16 +00:00
rum_enabled =
get_option (
options ,
:rum ,
" Would you like to use RUM indices? " ,
" n "
) === " y "
2019-07-09 19:57:41 +00:00
listen_port =
get_option (
options ,
:listen_port ,
" What port will the app listen to (leave it if you are using the default setup with nginx)? " ,
4000
)
listen_ip =
get_option (
options ,
:listen_ip ,
" What ip will the app listen to (leave it if you are using the default setup with nginx)? " ,
" 127.0.0.1 "
)
2019-06-20 00:59:16 +00:00
uploads_dir =
get_option (
options ,
2019-07-05 04:19:27 +00:00
:uploads_dir ,
2019-06-20 00:59:16 +00:00
" What directory should media uploads go in (when using the local uploader)? " ,
2020-07-09 15:53:51 +00:00
Config . get ( [ Pleroma.Uploaders.Local , :uploads ] )
2019-06-20 00:59:16 +00:00
)
2020-05-20 18:16:40 +00:00
|> Path . expand ( )
2019-06-20 00:59:16 +00:00
static_dir =
get_option (
options ,
:static_dir ,
" What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)? " ,
2020-07-09 15:53:51 +00:00
Config . get ( [ :instance , :static_dir ] )
2019-06-20 00:59:16 +00:00
)
2020-05-20 18:16:40 +00:00
|> Path . expand ( )
2019-06-20 00:59:16 +00:00
2022-02-20 12:46:29 +00:00
{ strip_uploads_location_message , strip_uploads_location_default } =
2020-12-12 17:37:14 +00:00
if Pleroma.Utils . command_available? ( " exiftool " ) do
{ " Do you want to strip location (GPS) data from uploaded images? This requires exiftool, it was detected as installed. (y/n) " ,
" y " }
else
{ " 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) " ,
" n " }
end
2022-02-20 12:46:29 +00:00
strip_uploads_location =
2020-10-12 16:18:39 +00:00
get_option (
options ,
2022-02-20 12:46:29 +00:00
:strip_uploads_location ,
strip_uploads_location_message ,
strip_uploads_location_default
2020-10-12 16:18:39 +00:00
) === " y "
2022-02-20 11:59:42 +00:00
{ read_uploads_description_message , read_uploads_description_default } =
2022-02-14 12:14:25 +00:00
if Pleroma.Utils . command_available? ( " exiftool " ) do
{ " Do you want to read data from uploaded files so clients can use it to prefill fields like image description? This requires exiftool, it was detected as installed. (y/n) " ,
" y " }
else
{ " Do you want to read data from uploaded files so clients can use it to prefill fields like image description? This requires exiftool, it was detected as not installed, please install it if you answer yes. (y/n) " ,
" n " }
end
2022-02-20 11:59:42 +00:00
read_uploads_description =
2022-02-14 12:14:25 +00:00
get_option (
options ,
2022-02-20 11:59:42 +00:00
:read_uploads_description ,
read_uploads_description_message ,
read_uploads_description_default
2022-02-14 12:14:25 +00:00
) === " y "
2020-10-12 16:18:39 +00:00
anonymize_uploads =
get_option (
options ,
:anonymize_uploads ,
" Do you want to anonymize the filenames of uploads? (y/n) " ,
" n "
) === " y "
dedupe_uploads =
get_option (
options ,
:dedupe_uploads ,
" Do you want to deduplicate uploaded files? (y/n) " ,
" n "
) === " y "
2020-02-24 19:52:38 +00:00
Config . put ( [ :instance , :static_dir ] , static_dir )
2018-06-29 00:24:51 +00:00
secret = :crypto . strong_rand_bytes ( 64 ) |> Base . encode64 ( ) |> binary_part ( 0 , 64 )
2019-04-20 12:42:19 +00:00
jwt_secret = :crypto . strong_rand_bytes ( 64 ) |> Base . encode64 ( ) |> binary_part ( 0 , 64 )
2019-01-21 00:16:41 +00:00
signing_salt = :crypto . strong_rand_bytes ( 8 ) |> Base . encode64 ( ) |> binary_part ( 0 , 8 )
2021-12-15 21:17:11 +00:00
lv_signing_salt = :crypto . strong_rand_bytes ( 8 ) |> Base . encode64 ( ) |> binary_part ( 0 , 8 )
2018-12-06 17:16:51 +00:00
{ web_push_public_key , web_push_private_key } = :crypto . generate_key ( :ecdh , :prime256v1 )
2019-06-21 16:30:25 +00:00
template_dir = Application . app_dir ( :pleroma , " priv " ) <> " /templates "
2018-06-29 00:24:51 +00:00
result_config =
EEx . eval_file (
2019-06-21 16:30:25 +00:00
template_dir <> " /sample_config.eex " ,
2018-06-29 00:24:51 +00:00
domain : domain ,
2018-12-15 10:00:54 +00:00
port : port ,
2018-06-29 00:24:51 +00:00
email : email ,
2019-04-10 10:57:41 +00:00
notify_email : notify_email ,
2018-06-29 00:24:51 +00:00
name : name ,
dbhost : dbhost ,
dbname : dbname ,
dbuser : dbuser ,
dbpass : dbpass ,
2018-12-06 17:16:51 +00:00
secret : secret ,
2019-04-20 12:42:19 +00:00
jwt_secret : jwt_secret ,
2019-01-21 00:16:41 +00:00
signing_salt : signing_salt ,
2021-12-15 21:17:11 +00:00
lv_signing_salt : lv_signing_salt ,
2018-12-06 17:16:51 +00:00
web_push_public_key : Base . url_encode64 ( web_push_public_key , padding : false ) ,
2019-06-14 15:45:05 +00:00
web_push_private_key : Base . url_encode64 ( web_push_private_key , padding : false ) ,
2019-06-20 00:59:16 +00:00
db_configurable? : db_configurable? ,
static_dir : static_dir ,
2019-06-22 09:54:16 +00:00
uploads_dir : uploads_dir ,
2019-07-09 19:57:41 +00:00
rum_enabled : rum_enabled ,
listen_ip : listen_ip ,
2020-10-12 16:18:39 +00:00
listen_port : listen_port ,
upload_filters :
upload_filters ( %{
2022-02-20 12:46:29 +00:00
strip_location : strip_uploads_location ,
2022-02-20 11:59:42 +00:00
read_description : read_uploads_description ,
2020-10-12 16:18:39 +00:00
anonymize : anonymize_uploads ,
dedupe : dedupe_uploads
} )
2018-06-29 00:24:51 +00:00
)
result_psql =
EEx . eval_file (
2019-06-21 16:30:25 +00:00
template_dir <> " /sample_psql.eex " ,
2018-06-29 00:24:51 +00:00
dbname : dbname ,
dbuser : dbuser ,
2019-06-22 09:54:16 +00:00
dbpass : dbpass ,
rum_enabled : rum_enabled
2018-06-29 00:24:51 +00:00
)
2021-01-28 09:39:53 +00:00
config_dir = Path . dirname ( config_path )
psql_dir = Path . dirname ( psql_path )
2021-01-28 10:20:25 +00:00
2023-06-21 22:58:05 +00:00
# Note: Distros requiring group read (0o750) on those directories should
# pre-create the directories.
2021-01-28 09:39:53 +00:00
[ config_dir , psql_dir , static_dir , uploads_dir ]
|> Enum . reject ( & File . exists? / 1 )
2023-06-21 22:58:05 +00:00
|> Enum . each ( fn dir ->
File . mkdir_p! ( dir )
File . chmod! ( dir , 0o700 )
end )
2021-01-28 09:39:53 +00:00
2019-06-21 23:07:05 +00:00
shell_info ( " Writing config to #{ config_path } . " )
2018-06-29 00:24:51 +00:00
2023-06-21 22:58:05 +00:00
# Sadly no fchmod(2) equivalent in Elixir…
File . touch! ( config_path )
File . chmod! ( config_path , 0o640 )
2018-06-29 00:24:51 +00:00
File . write ( config_path , result_config )
2019-06-21 23:07:05 +00:00
shell_info ( " Writing the postgres script to #{ psql_path } . " )
2018-06-29 00:24:51 +00:00
File . write ( psql_path , result_psql )
2020-05-20 18:16:40 +00:00
write_robots_txt ( static_dir , indexable , template_dir )
2019-04-02 19:09:16 +00:00
2019-06-19 23:05:19 +00:00
shell_info (
2020-02-25 19:13:08 +00:00
" \n All files successfully written! Refer to the installation instructions for your platform for next steps. "
2018-06-29 00:24:51 +00:00
)
2020-02-25 19:13:08 +00:00
if db_configurable? do
shell_info (
" 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. "
)
end
2018-06-29 00:24:51 +00:00
else
2019-06-19 23:05:19 +00:00
shell_error (
2018-06-29 00:24:51 +00:00
" The task would have overwritten the following files: \n " <>
2023-06-21 22:58:05 +00:00
Enum . map_join ( will_overwrite , & " - #{ &1 } \n " ) <> " Rerun with `--force` to overwrite them. "
2018-06-29 00:24:51 +00:00
)
end
end
2019-04-02 19:09:16 +00:00
2020-05-20 18:16:40 +00:00
defp write_robots_txt ( static_dir , indexable , template_dir ) do
2019-04-02 19:09:16 +00:00
robots_txt =
EEx . eval_file (
2019-06-21 16:30:25 +00:00
template_dir <> " /robots_txt.eex " ,
2019-04-02 19:09:16 +00:00
indexable : indexable
)
robots_txt_path = Path . join ( static_dir , " robots.txt " )
if File . exists? ( robots_txt_path ) do
File . cp! ( robots_txt_path , " #{ robots_txt_path } .bak " )
2019-06-19 23:05:19 +00:00
shell_info ( " Backing up existing robots.txt to #{ robots_txt_path } .bak " )
2019-04-02 19:09:16 +00:00
end
File . write ( robots_txt_path , robots_txt )
2019-06-19 23:05:19 +00:00
shell_info ( " Writing #{ robots_txt_path } . " )
2019-04-02 19:09:16 +00:00
end
2020-10-12 16:18:39 +00:00
defp upload_filters ( filters ) when is_map ( filters ) do
enabled_filters =
2022-02-20 12:46:29 +00:00
if filters . strip_location do
[ Pleroma.Upload.Filter.Exiftool.StripLocation ]
2020-10-12 16:18:39 +00:00
else
[ ]
end
2022-02-14 12:14:25 +00:00
enabled_filters =
2022-02-20 11:59:42 +00:00
if filters . read_description do
enabled_filters ++ [ Pleroma.Upload.Filter.Exiftool.ReadDescription ]
2022-02-14 12:14:25 +00:00
else
enabled_filters
end
2020-10-12 16:18:39 +00:00
enabled_filters =
if filters . anonymize do
enabled_filters ++ [ Pleroma.Upload.Filter.AnonymizeFilename ]
else
enabled_filters
end
enabled_filters =
if filters . dedupe do
enabled_filters ++ [ Pleroma.Upload.Filter.Dedupe ]
else
enabled_filters
end
enabled_filters
end
defp upload_filters ( _ ) , do : [ ]
2018-06-29 00:24:51 +00:00
end