Commit 76b97541 authored by Spctrl's avatar Spctrl

install: Set to stable v0.9.9 Pleroma branch

parent 759db728
defmodule Mix.Tasks.GenerateConfig do
use Mix.Task
@shortdoc "Generates a new config"
def run(_) do
IO.puts("--- Generating config files ---\n")
domain = "{DOMAIN}" |> String.trim()
name = "{SERVER_NAME}" |> String.trim()
email = "{EMAIL}" |> String.trim()
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
dbpass = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
resultSql = EEx.eval_file("lib/mix/tasks/sample_psql.eex", dbpass: dbpass)
result =
EEx.eval_file(
"lib/mix/tasks/sample_config.eex",
domain: domain,
email: email,
name: name,
secret: secret,
dbpass: dbpass
)
File.write("config/generated_config.exs", result)
File.write("config/setup_db.psql", resultSql)
end
end
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.Instance do
use Mix.Task
alias Mix.Tasks.Pleroma.Common
@shortdoc "Manages Pleroma instance"
@moduledoc """
Manages Pleroma instance.
## Generate a new instance config.
mix pleroma.instance gen [OPTION...]
If any options are left unspecified, you will be prompted interactively
## Options
- `-f`, `--force` - overwrite any output files
- `-o PATH`, `--output PATH` - the output file for the generated configuration
- `--output-psql PATH` - the output file for the generated PostgreSQL setup
- `--domain DOMAIN` - the domain of your instance
- `--instance-name INSTANCE_NAME` - the name of your instance
- `--admin-email ADMIN_EMAIL` - the email address of the instance admin
- `--dbhost HOSTNAME` - the hostname of the PostgreSQL database to use
- `--dbname DBNAME` - the name of the database to use
- `--dbuser DBUSER` - the user (aka role) to use for the database connection
- `--dbpass DBPASS` - the password to use for the database connection
"""
def run(["gen" | rest]) do
{options, [], []} =
OptionParser.parse(
rest,
strict: [
force: :boolean,
output: :string,
output_psql: :string,
domain: :string,
instance_name: :string,
admin_email: :string,
dbhost: :string,
dbname: :string,
dbuser: :string,
dbpass: :string
],
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)
unless not proceed? do
[domain, port | _] =
String.split(
Common.get_option(
options,
:domain,
"What domain will your instance use? (e.g pleroma.soykaf.com)"
),
":"
) ++ [443]
name =
Common.get_option(
options,
:instance_name,
"What is the name of your instance? (e.g. Pleroma/Soykaf)"
)
email = Common.get_option(options, :admin_email, "What is your admin email address?")
dbhost =
Common.get_option(options, :dbhost, "What is the hostname of your database?", "localhost")
dbname =
Common.get_option(options, :dbname, "What is the name of your database?", "pleroma_dev")
dbuser =
Common.get_option(
options,
:dbuser,
"What is the user used to connect to your database?",
"pleroma"
)
dbpass =
Common.get_option(
options,
:dbpass,
"What is the password used to connect to your database?",
:crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64),
"autogenerated"
)
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
{web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
result_config =
EEx.eval_file(
"sample_config.eex" |> Path.expand(__DIR__),
domain: domain,
port: port,
email: email,
name: name,
dbhost: dbhost,
dbname: dbname,
dbuser: dbuser,
dbpass: dbpass,
version: Pleroma.Mixfile.project() |> Keyword.get(:version),
secret: secret,
web_push_public_key: Base.url_encode64(web_push_public_key, padding: false),
web_push_private_key: Base.url_encode64(web_push_private_key, padding: false)
)
result_psql =
EEx.eval_file(
"sample_psql.eex" |> Path.expand(__DIR__),
dbname: dbname,
dbuser: dbuser,
dbpass: dbpass
)
Mix.shell().info(
"Writing config to #{config_path}. You should rename it to config/prod.secret.exs or config/dev.secret.exs."
)
File.write(config_path, result_config)
Mix.shell().info("Writing #{psql_path}.")
File.write(psql_path, result_psql)
Mix.shell().info(
"\n" <>
"""
To get started:
1. Verify the contents of the generated files.
2. Run `sudo -u postgres psql -f #{Common.escape_sh_path(psql_path)}`.
""" <>
if config_path in ["config/dev.secret.exs", "config/prod.secret.exs"] do
""
else
"3. Run `mv #{Common.escape_sh_path(config_path)} 'config/prod.secret.exs'`."
end
)
else
Mix.shell().error(
"The task would have overwritten the following files:\n" <>
(Enum.map(paths, &"- #{&1}\n") |> Enum.join("")) <>
"Rerun with `--force` to overwrite them."
)
end
end
end
defmodule Mix.Tasks.Pleroma.User do
use Mix.Task
import Ecto.Changeset
alias Pleroma.{Repo, User}
alias Mix.Tasks.Pleroma.Common
@shortdoc "Manages Pleroma users"
@moduledoc """
Manages Pleroma users.
## Create a new user.
mix pleroma.user new NICKNAME EMAIL [OPTION...]
Options:
- `--name NAME` - the user's name (i.e., "Lain Iwakura")
- `--bio BIO` - the user's bio
- `--password PASSWORD` - the user's password
- `--moderator`/`--no-moderator` - whether the user is a moderator
- `--admin`/`--no-admin` - whether the user is an admin
## Generate an invite link.
mix pleroma.user invite
## Delete the user's account.
mix pleroma.user rm NICKNAME
## Deactivate or activate the user's account.
mix pleroma.user toggle_activated NICKNAME
## Unsubscribe local users from user's account and deactivate it
mix pleroma.user unsubscribe NICKNAME
## Create a password reset link.
mix pleroma.user reset_password NICKNAME
## Set the value of the given user's settings.
mix pleroma.user set NICKNAME [OPTION...]
Options:
- `--locked`/`--no-locked` - whether the user's account is locked
- `--moderator`/`--no-moderator` - whether the user is a moderator
- `--admin`/`--no-admin` - whether the user is an admin
"""
def run(["new", nickname, email | rest]) do
{options, [], []} =
OptionParser.parse(
rest,
strict: [
name: :string,
bio: :string,
password: :string,
moderator: :boolean,
admin: :boolean,
assume_yes: :boolean
]
)
name = Keyword.get(options, :name, nickname)
bio = Keyword.get(options, :bio, "")
{password, generated_password?} =
case Keyword.get(options, :password) do
nil ->
{:crypto.strong_rand_bytes(16) |> Base.encode64(), true}
password ->
{password, false}
end
moderator? = Keyword.get(options, :moderator, false)
admin? = Keyword.get(options, :admin, false)
Mix.shell().info("""
A user will be created with the following information:
- nickname: #{nickname}
- email: #{email}
- password: #{
if(generated_password?, do: "[generated; a reset link will be created]", else: password)
}
- name: #{name}
- bio: #{bio}
- moderator: #{if(moderator?, do: "true", else: "false")}
- admin: #{if(admin?, do: "true", else: "false")}
""")
proceed? = true
unless not proceed? do
Common.start_pleroma()
params = %{
nickname: nickname,
email: email,
password: password,
password_confirmation: password,
name: name,
bio: bio
}
user = User.register_changeset(%User{}, params)
Repo.insert!(user)
Mix.shell().info("User #{nickname} created")
if moderator? do
run(["set", nickname, "--moderator"])
end
if admin? do
run(["set", nickname, "--admin"])
end
if generated_password? do
run(["reset_password", nickname])
end
else
Mix.shell().info("User will not be created.")
end
end
def run(["rm", nickname]) do
Common.start_pleroma()
with %User{local: true} = user <- User.get_by_nickname(nickname) do
User.delete(user)
Mix.shell().info("User #{nickname} deleted.")
else
_ ->
Mix.shell().error("No local user #{nickname}")
end
end
def run(["toggle_activated", nickname]) do
Common.start_pleroma()
with %User{} = user <- User.get_by_nickname(nickname) do
{:ok, user} = User.deactivate(user, !user.info.deactivated)
Mix.shell().info(
"Activation status of #{nickname}: #{if(user.info.deactivated, do: "de", else: "")}activated"
)
else
_ ->
Mix.shell().error("No user #{nickname}")
end
end
def run(["reset_password", nickname]) do
Common.start_pleroma()
with %User{local: true} = user <- User.get_by_nickname(nickname),
{:ok, token} <- Pleroma.PasswordResetToken.create_token(user) do
Mix.shell().info("Generated password reset token for #{user.nickname}")
IO.puts(
"URL: #{
Pleroma.Web.Router.Helpers.util_url(
Pleroma.Web.Endpoint,
:show_password_reset,
token.token
)
}"
)
else
_ ->
Mix.shell().error("No local user #{nickname}")
end
end
def run(["unsubscribe", nickname]) do
Common.start_pleroma()
with %User{} = user <- User.get_by_nickname(nickname) do
Mix.shell().info("Deactivating #{user.nickname}")
User.deactivate(user)
{:ok, friends} = User.get_friends(user)
Enum.each(friends, fn friend ->
user = Repo.get(User, user.id)
Mix.shell().info("Unsubscribing #{friend.nickname} from #{user.nickname}")
User.unfollow(user, friend)
end)
:timer.sleep(500)
user = Repo.get(User, user.id)
if length(user.following) == 0 do
Mix.shell().info("Successfully unsubscribed all followers from #{user.nickname}")
end
else
_ ->
Mix.shell().error("No user #{nickname}")
end
end
def run(["set", nickname | rest]) do
Common.start_pleroma()
{options, [], []} =
OptionParser.parse(
rest,
strict: [
moderator: :boolean,
admin: :boolean,
locked: :boolean
]
)
with %User{local: true} = user <- User.get_by_nickname(nickname) do
user =
case Keyword.get(options, :moderator) do
nil -> user
value -> set_moderator(user, value)
end
user =
case Keyword.get(options, :locked) do
nil -> user
value -> set_locked(user, value)
end
_user =
case Keyword.get(options, :admin) do
nil -> user
value -> set_admin(user, value)
end
else
_ ->
Mix.shell().error("No local user #{nickname}")
end
end
def run(["invite"]) do
Common.start_pleroma()
with {:ok, token} <- Pleroma.UserInviteToken.create_token() do
Mix.shell().info("Generated user invite token")
url =
Pleroma.Web.Router.Helpers.redirect_url(
Pleroma.Web.Endpoint,
:registration_page,
token.token
)
IO.puts(url)
else
_ ->
Mix.shell().error("Could not create invite token.")
end
end
defp set_moderator(user, value) do
info_cng = User.Info.admin_api_update(user.info, %{is_moderator: value})
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
Mix.shell().info("Moderator status of #{user.nickname}: #{user.info.is_moderator}")
user
end
defp set_admin(user, value) do
info_cng = User.Info.admin_api_update(user.info, %{is_admin: value})
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
Mix.shell().info("Admin status of #{user.nickname}: #{user.info.is_admin}")
user
end
defp set_locked(user, value) do
info_cng = User.Info.user_upgrade(user.info, %{locked: value})
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
Mix.shell().info("Locked status of #{user.nickname}: #{user.info.locked}")
user
end
end
{
"name": "Pleroma tryout app",
"name": "Pleroma",
"id": "pleroma_ynh",
"packaging_format": 1,
"description": {
"en": "Pleroma package for YunoHost application."
"en": "Pleroma package for YunoHost"
},
"version": "0.1.0~ynh1",
"url": "",
"version": "0.9.9~ynh1",
"url": "https://git.pleroma.social/pleroma/pleroma",
"license": "free",
"maintainer": {
"name": "Ilja",
"email": "spctrl@spectraltheorem.be",
"url": ""
"url": "https://gitlab.com/Spctrl/pleroma_ynh"
},
"requirements": {
"yunohost": ">= 3.0.0"
"yunohost": ">= 3.2.2"
},
"multi_instance": true,
"services": [
......@@ -56,15 +56,15 @@
{
"name": "instance_user",
"ask": {
"en": "A user with moderator rights will be created. Give a username for this user."
"en": "A admin/moderator user will be created. Give a username for this user."
},
"example": "moderator"
"example": "admin"
},
{
"name": "instance_user_password",
"type": "password",
"ask": {
"en": "Set the password for the moderator user"
"en": "Set the password for the admin user"
},
"example": "myreallystrongpassword"
},
......@@ -72,16 +72,16 @@
"name": "instance_user_password_verify",
"type": "password",
"ask": {
"en": "Type the password for the moderator user again"
"en": "Type the password for the admin user again"
},
"example": "myreallystrongpassword"
},
{
"name": "instance_user_mail",
"ask": {
"en": "The mailadress for the moderator user. This will be the mailadres for the moderator user and will also be visseble for other people on your pleroma instance."
"en": "The mailadress for the admin user. This will be the mailadres for the admin user and will also be publicly visseble"
},
"example": "pleroma@mypleroma.org"
"example": "admin@mypleroma.org"
}
]
}
......
......@@ -25,3 +25,43 @@ ynh_string_random() {
cat /dev/urandom | tr -c -d 'A-Za-z0-9' | head -c ${1:-24}
}
# Add setting to configfile if not already present. If already present the correct value will be set
#
# usage: pleroma_ynh_add_setting scope, setting, value, settingsfile
# | arg: scope - Settings are ordered in several bocks. This is the name of the block e.g. "config :pleroma, :instance"
# | arg: setting - The name of the setting e.g. "registrations_open"
# | arg: value - The value of the setting e.g. "true"
# | arg: settingsfile - The file where the custom settings are stored
pleroma_ynh_add_setting() {
# "Check if setting is already in the file"
if ! ( cat "$4" | grep "$2: " )
then # Add setting
# "Check if scope is in the file"
if ( cat "$4" | grep "$1," )
then
# "The scope is in the file, but the setting is not"
# Note that we leave a trailling comma. Since the scope is in the file, we know that there is at least one setting for it as well.
ynh_replace_string "$1," "$1,\r\n $2: $3," "$4"
else
# "Neither the scope nor the setting is in the file, so we add both"
# There isn't a second option, so no trailing comma
echo "$1," >> "$4"
echo " $2: $3" >> "$4"
echo "" >> "$4"
fi
# Setting exists, so we just need to set the value
ynh_replace_string "$2: [^,\n]*" "$2: $3" $settingsfile
fi
}
# Converts an integer into a booleanstring
#
# int |-> "false" if int=0
# "true" otherwise
#
# usage: pleroma_ynh_int_to_boolstring int
# | arg: int - The integer, usually 1 or 0, to convert
pleroma_ynh_int_to_boolstring(){
! [ $1 -eq 0 ] && echo "true" || echo "false"
}
......@@ -24,6 +24,8 @@ ynh_abort_if_errors
# LOAD SETTINGS
#=================================================
ynh_print_info "Loading settings"
app=$YNH_APP_INSTANCE_NAME
final_path=$(ynh_app_setting_get $app final_path)
......@@ -36,6 +38,8 @@ db_name=$(ynh_app_setting_get $app db_name)
# BACKUP THE NGINX CONFIGURATION
#=================================================
ynh_print_info "Backing up nginx configuration"
ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf"
ynh_backup "/etc/nginx/conf.d/$app-cache.conf"
......@@ -43,6 +47,8 @@ ynh_backup "/etc/nginx/conf.d/$app-cache.conf"
# BACKUP THE POSTGRESQL DATABASE
#=================================================
ynh_print_info "Backing up database"
mkdir --parents $final_path/backup
chown postgres $final_path/backup
touch $final_path/backup/$db_name.sql
......@@ -53,21 +59,19 @@ su - postgres -c "pg_dump $db_name > $final_path/backup/$db_name.sql"
# BACKUP THE APP MAIN DIR
#=================================================
ynh_print_info "Backing up main directory"
ynh_backup "$final_path"
# TODO: Check if I can remove _$final_path/backup/$db_name.sql_ after backup
# TODO: If _$final_path/backup/$db_name.sql_ can be removed, _touch $final_path/backup/$db_name.sql_ can be scratched
# TODO: If _$final_path/backup/$db_name.sql_ can be removed, _chown postgres $final_path/backup/$db_name.sql_ can be scratched
#================================================
# SPECIFIC BACKUP
#=================================================
# BACKUP LOGROTATE
# BACKUP SYSTEMD
#=================================================
#ynh_backup "/etc/logrotate.d/$app"
ynh_print_info "Backing up systemd configuration"
#=================================================
# BACKUP SYSTEMD
#=================================================
systemd_location=/usr/lib/systemd/system
ynh_backup "$systemd_location/$app.service"
......@@ -23,8 +23,10 @@ domain=$YNH_APP_ARG_DOMAIN
path_url="/"
server_name=$YNH_APP_ARG_INSTANCE_NAME
instance_user=$YNH_APP_ARG_INSTANCE_USER
ynh_print_OFF
instance_user_password=$YNH_APP_ARG_INSTANCE_USER_PASSWORD
instance_user_password_verify=$YNH_APP_ARG_INSTANCE_USER_PASSWORD_VERIFY
ynh_print_ON
instance_user_mail=$YNH_APP_ARG_INSTANCE_USER_MAIL
email=$instance_user_mail
is_public=$YNH_APP_ARG_IS_PUBLIC
......@@ -32,13 +34,15 @@ allow_scopes=$YNH_APP_ARG_ALLOW_SCOPES
app=$YNH_APP_INSTANCE_NAME
db_name=$app
#=================================================
#==================================================
# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS
#=================================================
#==================================================
ynh_print_OFF
if [ $instance_user_password != $instance_user_password_verify ]
then ynh_die "Passwords didn't match"
fi
ynh_print_ON
final_path=/var/www/$app
test ! -e "$final_path" || ynh_die "This path already contains a folder"
......@@ -101,36 +105,22 @@ useradd $app --home-dir=$final_path
#=================================================
ynh_print_info "Downloading source"
git clone https://git.pleroma.social/pleroma/pleroma $final_path/pleroma
# git clone --branch fix_486 https://git.pleroma.social/ilja/pleroma/ $final_path/pleroma
git clone --branch v0.9.9 https://git.pleroma.social/pleroma/pleroma/ $final_path/pleroma
# To only clone in one branch, we could also do
# git clone --single-branch --branch v0.9.9 https://git.pleroma.social/pleroma/pleroma/
ynh_print_info "Building the Pleroma instance"
# replace the generate_config file with a modified one to have it non-interactive
# TODO: there's a merge comming in Pleroma that makes it all non-interactive
# https://git.pleroma.social/pleroma/pleroma/merge_requests/243
# this will simplify this whole block
cp ../conf/generate_config.ex $final_path/pleroma/lib/mix/tasks/generate_config.ex
# Replace files with modified ones to make it non-interactive
# These'll be fixed with https://git.pleroma.social/pleroma/pleroma/issues/485
# and https://git.pleroma.social/pleroma/pleroma/issues/486
cp ../conf/instance.ex $final_path/pleroma/lib/mix/tasks/pleroma/instance.ex
cp ../conf/user.ex $final_path/pleroma/lib/mix/tasks/pleroma/user.ex
chown -R $app: $final_path
ynh_replace_string "{DOMAIN}" "$domain" "$final_path/pleroma/lib/mix/tasks/generate_config.ex"
ynh_replace_string "{SERVER_NAME}" "$server_name" "$final_path/pleroma/lib/mix/tasks/generate_config.ex"
ynh_replace_string "{EMAIL}" "$email" "$final_path/pleroma/lib/mix/tasks/generate_config.ex"
su - $app -c "cd $final_path/pleroma;mix local.hex --force;mix deps.get;mix local.rebar --force;mix generate_config;cp config/generated_config.exs config/prod.secret.exs;"
# Replace the default Pleroma variables in the config files whit the ones to use on ynh
ynh_replace_string "pleroma" "PLACEHOLDER" "$final_path/pleroma/config/setup_db.psql"
ynh_replace_string "PLACEHOLDER_dev" "$db_name" "$final_path/pleroma/config/setup_db.psql"
ynh_replace_string "PLACEHOLDER" "$app" "$final_path/pleroma/config/setup_db.psql"
ynh_replace_string "username: \"pleroma\"" "username: \"$app\"" "$final_path/pleroma/config/generated_config.exs"
ynh_replace_string "pleroma_dev" "$db_name" "$final_path/pleroma/config/generated_config.exs"
ynh_replace_string "username: \"pleroma\"" "username: \"$app\"" "$final_path/pleroma/config/prod.secret.exs"
ynh_replace_string "pleroma_dev" "$db_name" "$final_path/pleroma/config/prod.secret.exs"
ynh_replace_string "port: 4000" "port: $port" "$final_path/pleroma/config/prod.exs"
ynh_replace_string "port: 4000" "port: $port" "$final_path/pleroma/config/dev.exs"
su - $app -c "cd $final_path/pleroma;mix local.hex --force;mix deps.get;mix local.rebar --force;mix pleroma.instance gen --domain "$domain" --instance-name "$server_name" --admin-email "$email" --dbhost localhost --dbname "$db_name" --dbuser "$app" --dbpass "$(ynh_string_random 32)";cp config/generated_config.exs config/prod.secret.exs;"
# Check that there are no unreplaced variables in the generated config files
cat $final_path/pleroma/config/generated_config.exs | grep "<%= .* %>" && ynh_die "$final_path/pleroma/config/generated_config.exs has unset variables"
......@@ -156,37 +146,10 @@ su - $app -c "cd $final_path/pleroma;mix local.rebar --force;mix local.hex --for
ynh_print_info "Configuring the instance"
# Check and set registrations open/closed
if [ $is_public -eq 1 ]
then
ynh_replace_string "registrations_open: false" "registrations_open: true" "$final_path/pleroma/config/prod.secret.exs"
else
ynh_replace_string "registrations_open: true" "registrations_open: false" "$final_path/pleroma/config/prod.secret.exs"
fi