Compare commits
132 Commits
develop
...
release/1.
Author | SHA1 | Date |
---|---|---|
rinpatch | f5305d2815 | |
rinpatch | 7aa17c3e75 | |
kaniini | a067cf0f23 | |
rinpatch | b60ec3b173 | |
rinpatch | 7030721b31 | |
rinpatch | df8fda267e | |
rinpatch | c8694d6d7b | |
rinpatch | 31421916c0 | |
rinpatch | 13e7753382 | |
rinpatch | 821fb2a584 | |
rinpatch | 700d0a56a1 | |
rinpatch | 68e7bea354 | |
rinpatch | 231e5e7914 | |
Haelwenn (lanodan) Monnier | e17113d821 | |
kaniini | b9188361dc | |
Ariadne Conill | 65cc68ff2f | |
rinpatch | 5999b4c5b9 | |
kaniini | 9aec8fe242 | |
Ariadne Conill | 974488a52e | |
Ariadne Conill | acc3c0ed58 | |
rinpatch | 094db46923 | |
kaniini | d6da4a75ce | |
Ariadne Conill | dcb4711e92 | |
Ivan Tashkinov | 9fa2011c17 | |
Ivan Tashkinov | bc6d1f9ed9 | |
Ivan Tashkinov | 1a46a13d15 | |
Ivan Tashkinov | e652f83e5a | |
Ariadne Conill | 606ccbab03 | |
Ariadne Conill | 4681747ec1 | |
Ariadne Conill | c7a3a15c3d | |
Ariadne Conill | b3afc0bb32 | |
Ariadne Conill | d5df62edd8 | |
Ariadne Conill | 7a5e1d64a5 | |
Ariadne Conill | eed36278a6 | |
Ariadne Conill | fb77dc50aa | |
Ariadne Conill | 3af51afdd7 | |
Ariadne Conill | c9468c9a59 | |
Ariadne Conill | 4ccd3410a8 | |
Ariadne Conill | 7e2bc39f3c | |
Ariadne Conill | b8186c26fa | |
Ariadne Conill | e13edc2d3b | |
Ariadne Conill | 29db8dc799 | |
Ariadne Conill | 54405919d8 | |
rinpatch | 5af3c00072 | |
Maksim | 60c75d6740 | |
Ariadne Conill | 14efbcf1f9 | |
Ariadne Conill | 4d0dd04653 | |
Sergey Suprunenko | 25c818ed6f | |
Ariadne Conill | f7028ae8ac | |
Sergey Suprunenko | 48bd4ee933 | |
rinpatch | 7e412fd88a | |
rinpatch | f0c32364b7 | |
rinpatch | e5161961bd | |
rinpatch | 1807d3a115 | |
rinpatch | b85840b536 | |
Ariadne Conill | a7b947534c | |
Alexander Strizhakov | b9def3758a | |
Sachin Joshi | e08b97853f | |
Ariadne Conill | 8a8fe57670 | |
Sergey Suprunenko | 1310cdc24f | |
Haelwenn (lanodan) Monnier | 54d4ceec5c | |
Haelwenn (lanodan) Monnier | f270e33208 | |
Ariadne Conill | d2c3c64da5 | |
Haelwenn (lanodan) Monnier | 65bd927cf2 | |
Ariadne Conill | 951d8c28d1 | |
Thibaut Girka | a3654d9479 | |
Thibaut Girka | b29dcc8c1b | |
Thibaut Girka | 6525fbac95 | |
rinpatch | ba21d515d6 | |
rinpatch | dcd30e3ceb | |
kaniini | 9c499435f0 | |
Ariadne Conill | 455f2934b7 | |
rinpatch | 8998620d71 | |
kaniini | 0eff6349a0 | |
Ariadne Conill | 2536628cac | |
Ariadne Conill | d006742fd7 | |
Ariadne Conill | e5cb15ce2b | |
Ariadne Conill | d18a7dc0de | |
rinpatch | 2c2c075fd6 | |
Ariadne Conill | 59e60c6db1 | |
kaniini | cca9d64cb8 | |
Ivan Tashkinov | daf0d0dd9a | |
Ivan Tashkinov | 1e77e71fb2 | |
Ivan Tashkinov | 7fdbef3e1b | |
kaniini | ce6dfb6f06 | |
Ariadne Conill | d9aacbec4d | |
lain | 3e3b00f658 | |
Ariadne Conill | f685e887b3 | |
Sergey Suprunenko | 2b38961bf6 | |
rinpatch | 99989758ff | |
rinpatch | 1426358538 | |
rinpatch | 2914f8a749 | |
Bradley D. Thornton | 8b1b3e84f4 | |
tom79 | 1c364f7407 | |
tom79 | 109e7813c9 | |
rinpatch | 15aaffc6d8 | |
rinpatch | 67c5e6541e | |
rinpatch | 7486a917d4 | |
rinpatch | 0c028f345a | |
rinpatch | 48aed88dbd | |
rinpatch | fd4963006a | |
rinpatch | 876b5b45a3 | |
Ariadne Conill | 3ec6f34ef0 | |
rinpatch | 6a35c151c6 | |
Sachin Joshi | 1e5d889aec | |
Sachin Joshi | ccafecf9be | |
Roman Chvanikov | 9e88ab2cad | |
Roman Chvanikov | 494a611afe | |
lain | ed639376ac | |
lain | 8123578bf8 | |
kaniini | 5cb37412a2 | |
Ariadne Conill | e01bab843b | |
kaniini | ba26208cec | |
Ariadne Conill | f1147a3d7f | |
Haelwenn (lanodan) Monnier | c51b2abead | |
Haelwenn (lanodan) Monnier | 3e298cc85a | |
Ariadne Conill | 7523ab1495 | |
Ariadne Conill | 6b12cb60e9 | |
Ariadne Conill | cdf2ff8176 | |
Haelwenn (lanodan) Monnier | 48927b1d3b | |
Haelwenn (lanodan) Monnier | 1c79ec2c08 | |
Haelwenn (lanodan) Monnier | e7a472a11f | |
Ariadne Conill | 5e9befc7d4 | |
Ariadne Conill | 6d715b7702 | |
Ariadne Conill | 73a3dbe31e | |
rinpatch | 9504544d5b | |
rinpatch | 5bc9e6e0f3 | |
rinpatch | e9426d15d8 | |
rinpatch | 54d2873770 | |
rinpatch | 9b014eae68 | |
Yuji Nakao | 69585a3218 | |
Yuji Nakao | d9f8230d2c |
|
@ -25,7 +25,7 @@
|
||||||
#
|
#
|
||||||
# If you create your own checks, you must specify the source files for
|
# If you create your own checks, you must specify the source files for
|
||||||
# them here, so they can be loaded by Credo before running the analysis.
|
# them here, so they can be loaded by Credo before running the analysis.
|
||||||
requires: ["./test/credo/check/consistency/file_location.ex"],
|
requires: [],
|
||||||
#
|
#
|
||||||
# Credo automatically checks for updates, like e.g. Hex does.
|
# Credo automatically checks for updates, like e.g. Hex does.
|
||||||
# You can disable this behaviour below:
|
# You can disable this behaviour below:
|
||||||
|
@ -71,6 +71,7 @@
|
||||||
# set this value to 0 (zero).
|
# set this value to 0 (zero).
|
||||||
{Credo.Check.Design.TagTODO, exit_status: 0},
|
{Credo.Check.Design.TagTODO, exit_status: 0},
|
||||||
{Credo.Check.Design.TagFIXME, exit_status: 0},
|
{Credo.Check.Design.TagFIXME, exit_status: 0},
|
||||||
|
|
||||||
{Credo.Check.Readability.FunctionNames},
|
{Credo.Check.Readability.FunctionNames},
|
||||||
{Credo.Check.Readability.LargeNumbers},
|
{Credo.Check.Readability.LargeNumbers},
|
||||||
{Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 100},
|
{Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 100},
|
||||||
|
@ -83,7 +84,6 @@
|
||||||
# lanodan: I think PreferImplicitTry should be consistency, and the behaviour seems
|
# lanodan: I think PreferImplicitTry should be consistency, and the behaviour seems
|
||||||
# inconsistent, see: https://github.com/rrrene/credo/issues/224
|
# inconsistent, see: https://github.com/rrrene/credo/issues/224
|
||||||
{Credo.Check.Readability.PreferImplicitTry, false},
|
{Credo.Check.Readability.PreferImplicitTry, false},
|
||||||
{Credo.Check.Readability.PipeIntoAnonymousFunctions, exit_status: 0},
|
|
||||||
{Credo.Check.Readability.RedundantBlankLines},
|
{Credo.Check.Readability.RedundantBlankLines},
|
||||||
{Credo.Check.Readability.StringSigils},
|
{Credo.Check.Readability.StringSigils},
|
||||||
{Credo.Check.Readability.TrailingBlankLine},
|
{Credo.Check.Readability.TrailingBlankLine},
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
{Credo.Check.Readability.VariableNames},
|
{Credo.Check.Readability.VariableNames},
|
||||||
{Credo.Check.Readability.Semicolons},
|
{Credo.Check.Readability.Semicolons},
|
||||||
{Credo.Check.Readability.SpaceAfterCommas},
|
{Credo.Check.Readability.SpaceAfterCommas},
|
||||||
{Credo.Check.Readability.WithSingleClause, exit_status: 0},
|
|
||||||
{Credo.Check.Refactor.DoubleBooleanNegation},
|
{Credo.Check.Refactor.DoubleBooleanNegation},
|
||||||
{Credo.Check.Refactor.CondStatements},
|
{Credo.Check.Refactor.CondStatements},
|
||||||
{Credo.Check.Refactor.CyclomaticComplexity},
|
{Credo.Check.Refactor.CyclomaticComplexity},
|
||||||
|
@ -102,6 +102,7 @@
|
||||||
{Credo.Check.Refactor.Nesting},
|
{Credo.Check.Refactor.Nesting},
|
||||||
{Credo.Check.Refactor.PipeChainStart},
|
{Credo.Check.Refactor.PipeChainStart},
|
||||||
{Credo.Check.Refactor.UnlessWithElse},
|
{Credo.Check.Refactor.UnlessWithElse},
|
||||||
|
|
||||||
{Credo.Check.Warning.BoolOperationOnSameValues},
|
{Credo.Check.Warning.BoolOperationOnSameValues},
|
||||||
{Credo.Check.Warning.IExPry},
|
{Credo.Check.Warning.IExPry},
|
||||||
{Credo.Check.Warning.IoInspect},
|
{Credo.Check.Warning.IoInspect},
|
||||||
|
@ -130,7 +131,6 @@
|
||||||
|
|
||||||
# Custom checks can be created using `mix credo.gen.check`.
|
# Custom checks can be created using `mix credo.gen.check`.
|
||||||
#
|
#
|
||||||
{Credo.Check.Consistency.FileLocation}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
.*
|
|
||||||
*.md
|
|
||||||
AGPL-3
|
|
||||||
CC-BY-SA-4.0
|
|
||||||
COPYING
|
|
||||||
*file
|
|
||||||
elixir_buildpack.config
|
|
||||||
test/
|
|
||||||
|
|
||||||
# Required to get version
|
|
||||||
!.git
|
|
|
@ -1,3 +1,3 @@
|
||||||
[
|
[
|
||||||
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}", "priv/repo/migrations/*.exs", "priv/repo/optional_migrations/**/*.exs", "priv/scrubbers/*.ex"]
|
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
*.ex diff=elixir
|
|
||||||
*.exs diff=elixir
|
|
||||||
|
|
||||||
priv/static/instance/static.css diff=css
|
|
||||||
|
|
||||||
# Most of js/css files included in the repo are minified bundles,
|
|
||||||
# and we don't want to search/diff those as text files.
|
|
||||||
*.js binary
|
|
||||||
*.js.map binary
|
|
||||||
*.css binary
|
|
|
@ -3,10 +3,8 @@
|
||||||
/db
|
/db
|
||||||
/deps
|
/deps
|
||||||
/*.ez
|
/*.ez
|
||||||
/test/instance
|
|
||||||
/test/uploads
|
/test/uploads
|
||||||
/.elixir_ls
|
/.elixir_ls
|
||||||
/test/fixtures/DSCN0010_tmp.jpg
|
|
||||||
/test/fixtures/test_tmp.txt
|
/test/fixtures/test_tmp.txt
|
||||||
/test/fixtures/image_tmp.jpg
|
/test/fixtures/image_tmp.jpg
|
||||||
/test/tmp/
|
/test/tmp/
|
||||||
|
@ -28,12 +26,9 @@ erl_crash.dump
|
||||||
# variables.
|
# variables.
|
||||||
/config/*.secret.exs
|
/config/*.secret.exs
|
||||||
/config/generated_config.exs
|
/config/generated_config.exs
|
||||||
/config/runtime.exs
|
|
||||||
/config/*.env
|
|
||||||
|
|
||||||
|
|
||||||
# Database setup file, some may forget to delete it
|
# Database setup file, some may forget to delete it
|
||||||
/config/setup_db*.psql
|
/config/setup_db.psql
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env
|
.env
|
||||||
|
@ -43,19 +38,7 @@ erl_crash.dump
|
||||||
|
|
||||||
# Prevent committing docs files
|
# Prevent committing docs files
|
||||||
/priv/static/doc/*
|
/priv/static/doc/*
|
||||||
docs/generated_config.md
|
|
||||||
|
|
||||||
# Code test coverage
|
# Code test coverage
|
||||||
/cover
|
/cover
|
||||||
/Elixir.*.coverdata
|
/Elixir.*.coverdata
|
||||||
/coverage.xml
|
|
||||||
|
|
||||||
.idea
|
|
||||||
pleroma.iml
|
|
||||||
|
|
||||||
# asdf
|
|
||||||
.tool-versions
|
|
||||||
|
|
||||||
# Editor temp files
|
|
||||||
/*~
|
|
||||||
/*#
|
|
||||||
|
|
310
.gitlab-ci.yml
310
.gitlab-ci.yml
|
@ -1,196 +1,102 @@
|
||||||
image: git.pleroma.social:5050/pleroma/pleroma/ci-base
|
image: elixir:1.8.1
|
||||||
|
|
||||||
variables: &global_variables
|
variables:
|
||||||
POSTGRES_DB: pleroma_test
|
POSTGRES_DB: pleroma_test
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
DB_HOST: postgres
|
DB_HOST: postgres
|
||||||
DB_PORT: 5432
|
|
||||||
MIX_ENV: test
|
MIX_ENV: test
|
||||||
|
|
||||||
cache: &global_cache_policy
|
cache:
|
||||||
key:
|
key: ${CI_COMMIT_REF_SLUG}
|
||||||
files:
|
|
||||||
- mix.lock
|
|
||||||
paths:
|
paths:
|
||||||
- deps
|
- deps
|
||||||
- _build
|
- _build
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- test
|
- test
|
||||||
- benchmark
|
|
||||||
- deploy
|
- deploy
|
||||||
- release
|
- release
|
||||||
- docker
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- echo $MIX_ENV
|
- mix local.hex --force
|
||||||
- rm -rf _build/*/lib/pleroma
|
- mix local.rebar --force
|
||||||
- mix deps.get
|
|
||||||
|
|
||||||
after_script:
|
|
||||||
- rm -rf _build/*/lib/pleroma
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
only:
|
|
||||||
changes: &build_changes_policy
|
|
||||||
- ".gitlab-ci.yml"
|
|
||||||
- "**/*.ex"
|
|
||||||
- "**/*.exs"
|
|
||||||
- "mix.lock"
|
|
||||||
script:
|
script:
|
||||||
|
- mix deps.get
|
||||||
- mix compile --force
|
- mix compile --force
|
||||||
|
|
||||||
spec-build:
|
docs-build:
|
||||||
stage: test
|
stage: build
|
||||||
only:
|
only:
|
||||||
changes:
|
- master@pleroma/pleroma
|
||||||
- ".gitlab-ci.yml"
|
- develop@pleroma/pleroma
|
||||||
- "lib/pleroma/web/api_spec/**/*.ex"
|
variables:
|
||||||
- "lib/pleroma/web/api_spec.ex"
|
MIX_ENV: dev
|
||||||
|
script:
|
||||||
|
- mix deps.get
|
||||||
|
- mix compile
|
||||||
|
- mix docs
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- spec.json
|
- priv/static/doc
|
||||||
script:
|
|
||||||
- mix pleroma.openapi_spec spec.json
|
|
||||||
|
|
||||||
benchmark:
|
|
||||||
stage: benchmark
|
|
||||||
when: manual
|
|
||||||
variables:
|
|
||||||
MIX_ENV: benchmark
|
|
||||||
services:
|
|
||||||
- name: postgres:9.6-alpine
|
|
||||||
alias: postgres
|
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
|
||||||
script:
|
|
||||||
- mix ecto.create
|
|
||||||
- mix ecto.migrate
|
|
||||||
- mix pleroma.load_testing
|
|
||||||
|
|
||||||
unit-testing:
|
unit-testing:
|
||||||
stage: test
|
stage: test
|
||||||
only:
|
|
||||||
changes: *build_changes_policy
|
|
||||||
cache: &testing_cache_policy
|
|
||||||
<<: *global_cache_policy
|
|
||||||
policy: pull
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- name: postgres:13-alpine
|
- name: lainsoykaf/postgres-with-rum
|
||||||
alias: postgres
|
alias: postgres
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||||
script:
|
script:
|
||||||
|
- mix deps.get
|
||||||
- mix ecto.create
|
- mix ecto.create
|
||||||
- mix ecto.migrate
|
- mix ecto.migrate
|
||||||
- mix test --cover --preload-modules
|
- mix coveralls --trace --preload-modules
|
||||||
coverage: '/^Line total: ([^ ]*%)$/'
|
|
||||||
artifacts:
|
|
||||||
reports:
|
|
||||||
coverage_report:
|
|
||||||
coverage_format: cobertura
|
|
||||||
path: coverage.xml
|
|
||||||
|
|
||||||
unit-testing-erratic:
|
|
||||||
stage: test
|
|
||||||
retry: 2
|
|
||||||
allow_failure: true
|
|
||||||
only:
|
|
||||||
changes: *build_changes_policy
|
|
||||||
cache: &testing_cache_policy
|
|
||||||
<<: *global_cache_policy
|
|
||||||
policy: pull
|
|
||||||
|
|
||||||
services:
|
|
||||||
- name: postgres:13-alpine
|
|
||||||
alias: postgres
|
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
|
||||||
script:
|
|
||||||
- mix ecto.create
|
|
||||||
- mix ecto.migrate
|
|
||||||
- mix test --only=erratic
|
|
||||||
|
|
||||||
# Removed to fix CI issue. In this early state it wasn't adding much value anyway.
|
|
||||||
# TODO Fix and reinstate federated testing
|
|
||||||
# federated-testing:
|
|
||||||
# stage: test
|
|
||||||
# cache: *testing_cache_policy
|
|
||||||
# services:
|
|
||||||
# - name: minibikini/postgres-with-rum:12
|
|
||||||
# alias: postgres
|
|
||||||
# command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
|
||||||
# script:
|
|
||||||
# - mix deps.get
|
|
||||||
# - mix ecto.create
|
|
||||||
# - mix ecto.migrate
|
|
||||||
# - epmd -daemon
|
|
||||||
# - mix test --trace --only federated
|
|
||||||
|
|
||||||
unit-testing-rum:
|
unit-testing-rum:
|
||||||
stage: test
|
stage: test
|
||||||
only:
|
|
||||||
changes: *build_changes_policy
|
|
||||||
cache: *testing_cache_policy
|
|
||||||
services:
|
services:
|
||||||
- name: minibikini/postgres-with-rum:12
|
- name: lainsoykaf/postgres-with-rum
|
||||||
alias: postgres
|
alias: postgres
|
||||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||||
variables:
|
variables:
|
||||||
<<: *global_variables
|
|
||||||
RUM_ENABLED: "true"
|
RUM_ENABLED: "true"
|
||||||
script:
|
script:
|
||||||
|
- mix deps.get
|
||||||
- mix ecto.create
|
- mix ecto.create
|
||||||
- mix ecto.migrate
|
- mix ecto.migrate
|
||||||
- "mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
|
- "mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
|
||||||
- mix test --preload-modules
|
- mix test --trace --preload-modules
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
image: ¤t_elixir elixir:1.12-alpine
|
|
||||||
stage: test
|
stage: test
|
||||||
only:
|
|
||||||
changes: *build_changes_policy
|
|
||||||
cache: *testing_cache_policy
|
|
||||||
before_script: ¤t_bfr_script
|
|
||||||
- apk update
|
|
||||||
- apk add build-base cmake file-dev git openssl
|
|
||||||
- mix local.hex --force
|
|
||||||
- mix local.rebar --force
|
|
||||||
- mix deps.get
|
|
||||||
script:
|
script:
|
||||||
- mix format --check-formatted
|
- mix format --check-formatted
|
||||||
|
|
||||||
analysis:
|
analysis:
|
||||||
stage: test
|
stage: test
|
||||||
only:
|
|
||||||
changes: *build_changes_policy
|
|
||||||
cache: *testing_cache_policy
|
|
||||||
script:
|
script:
|
||||||
|
- mix deps.get
|
||||||
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
|
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
|
||||||
|
|
||||||
cycles:
|
|
||||||
image: *current_elixir
|
|
||||||
stage: test
|
|
||||||
only:
|
|
||||||
changes: *build_changes_policy
|
|
||||||
cache: {}
|
|
||||||
before_script: *current_bfr_script
|
|
||||||
script:
|
|
||||||
- mix compile
|
|
||||||
- mix xref graph --format cycles --label compile | awk '{print $0} END{exit ($0 != "No cycles found")}'
|
|
||||||
|
|
||||||
docs-deploy:
|
docs-deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
cache: *testing_cache_policy
|
image: alpine:3.9
|
||||||
image: alpine:latest
|
|
||||||
only:
|
only:
|
||||||
- stable@pleroma/pleroma
|
- stable@pleroma/pleroma
|
||||||
- develop@pleroma/pleroma
|
- develop@pleroma/pleroma
|
||||||
before_script:
|
before_script:
|
||||||
- apk add curl
|
- apk update && apk add openssh-client rsync
|
||||||
script:
|
script:
|
||||||
- curl -X POST -F"token=$DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" https://git.pleroma.social/api/v4/projects/673/trigger/pipeline
|
- mkdir -p ~/.ssh
|
||||||
|
- echo "${SSH_HOST_KEY}" > ~/.ssh/known_hosts
|
||||||
|
- eval $(ssh-agent -s)
|
||||||
|
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
||||||
|
- rsync -hrvz --delete -e "ssh -p ${SSH_PORT}" priv/static/doc/ "${SSH_USER_HOST_LOCATION}/${CI_COMMIT_REF_NAME}"
|
||||||
|
|
||||||
review_app:
|
review_app:
|
||||||
image: alpine:3.9
|
image: alpine:3.9
|
||||||
stage: deploy
|
stage: deploy
|
||||||
|
@ -213,27 +119,12 @@ review_app:
|
||||||
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
|
||||||
- ssh-keyscan -H "pleroma.online" >> ~/.ssh/known_hosts
|
- ssh-keyscan -H "pleroma.online" >> ~/.ssh/known_hosts
|
||||||
- (ssh -t dokku@pleroma.online -- apps:create "$CI_ENVIRONMENT_SLUG") || true
|
- (ssh -t dokku@pleroma.online -- apps:create "$CI_ENVIRONMENT_SLUG") || true
|
||||||
- (ssh -t dokku@pleroma.online -- git:set "$CI_ENVIRONMENT_SLUG" keep-git-dir true) || true
|
|
||||||
- ssh -t dokku@pleroma.online -- config:set "$CI_ENVIRONMENT_SLUG" APP_NAME="$CI_ENVIRONMENT_SLUG" APP_HOST="$CI_ENVIRONMENT_SLUG.pleroma.online" MIX_ENV=dokku
|
- ssh -t dokku@pleroma.online -- config:set "$CI_ENVIRONMENT_SLUG" APP_NAME="$CI_ENVIRONMENT_SLUG" APP_HOST="$CI_ENVIRONMENT_SLUG.pleroma.online" MIX_ENV=dokku
|
||||||
- (ssh -t dokku@pleroma.online -- postgres:create $(echo $CI_ENVIRONMENT_SLUG | sed -e 's/-/_/g')_db) || true
|
- (ssh -t dokku@pleroma.online -- postgres:create $(echo $CI_ENVIRONMENT_SLUG | sed -e 's/-/_/g')_db) || true
|
||||||
- (ssh -t dokku@pleroma.online -- postgres:link $(echo $CI_ENVIRONMENT_SLUG | sed -e 's/-/_/g')_db "$CI_ENVIRONMENT_SLUG") || true
|
- (ssh -t dokku@pleroma.online -- postgres:link $(echo $CI_ENVIRONMENT_SLUG | sed -e 's/-/_/g')_db "$CI_ENVIRONMENT_SLUG") || true
|
||||||
- (ssh -t dokku@pleroma.online -- certs:add "$CI_ENVIRONMENT_SLUG" /home/dokku/server.crt /home/dokku/server.key) || true
|
- (ssh -t dokku@pleroma.online -- certs:add "$CI_ENVIRONMENT_SLUG" /home/dokku/server.crt /home/dokku/server.key) || true
|
||||||
- git push -f dokku@pleroma.online:$CI_ENVIRONMENT_SLUG $CI_COMMIT_SHA:refs/heads/master
|
- git push -f dokku@pleroma.online:$CI_ENVIRONMENT_SLUG $CI_COMMIT_SHA:refs/heads/master
|
||||||
|
|
||||||
spec-deploy:
|
|
||||||
stage: deploy
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- spec.json
|
|
||||||
only:
|
|
||||||
- develop@pleroma/pleroma
|
|
||||||
image: alpine:latest
|
|
||||||
before_script:
|
|
||||||
- apk add curl
|
|
||||||
script:
|
|
||||||
- curl -X POST -F"token=$API_DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" -F"variables[JOB_REF]=$CI_JOB_ID" https://git.pleroma.social/api/v4/projects/1130/trigger/pipeline
|
|
||||||
|
|
||||||
|
|
||||||
stop_review_app:
|
stop_review_app:
|
||||||
image: alpine:3.9
|
image: alpine:3.9
|
||||||
stage: deploy
|
stage: deploy
|
||||||
|
@ -254,14 +145,13 @@ stop_review_app:
|
||||||
|
|
||||||
amd64:
|
amd64:
|
||||||
stage: release
|
stage: release
|
||||||
image: elixir:1.11.4
|
# TODO: Replace with upstream image when 1.9.0 comes out
|
||||||
|
image: rinpatch/elixir:1.9.0-rc.0
|
||||||
only: &release-only
|
only: &release-only
|
||||||
- stable@pleroma/pleroma
|
- stable@pleroma/pleroma
|
||||||
- develop@pleroma/pleroma
|
- develop@pleroma/pleroma
|
||||||
- /^maint/.*$/@pleroma/pleroma
|
- /^maint/.*$/@pleroma/pleroma
|
||||||
- /^release/.*$/@pleroma/pleroma
|
- /^release/.*$/@pleroma/pleroma
|
||||||
tags:
|
|
||||||
- amd64
|
|
||||||
artifacts: &release-artifacts
|
artifacts: &release-artifacts
|
||||||
name: "pleroma-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
|
name: "pleroma-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
|
||||||
paths:
|
paths:
|
||||||
|
@ -279,8 +169,7 @@ amd64:
|
||||||
variables: &release-variables
|
variables: &release-variables
|
||||||
MIX_ENV: prod
|
MIX_ENV: prod
|
||||||
before_script: &before-release
|
before_script: &before-release
|
||||||
- apt-get update && apt-get install -y cmake libmagic-dev
|
- echo "import Mix.Config" > config/prod.secret.exs
|
||||||
- echo "import Config" > config/prod.secret.exs
|
|
||||||
- mix local.hex --force
|
- mix local.hex --force
|
||||||
- mix local.rebar --force
|
- mix local.rebar --force
|
||||||
script: &release
|
script: &release
|
||||||
|
@ -294,14 +183,13 @@ amd64-musl:
|
||||||
stage: release
|
stage: release
|
||||||
artifacts: *release-artifacts
|
artifacts: *release-artifacts
|
||||||
only: *release-only
|
only: *release-only
|
||||||
image: elixir:1.11.4-alpine
|
# TODO: Replace with upstream image when 1.9.0 comes out
|
||||||
tags:
|
image: rinpatch/elixir:1.9.0-rc.0-alpine
|
||||||
- amd64
|
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: &before-release-musl
|
before_script: &before-release-musl
|
||||||
- apk add git build-base cmake file-dev openssl
|
- apk add git gcc g++ musl-dev make
|
||||||
- echo "import Config" > config/prod.secret.exs
|
- echo "import Mix.Config" > config/prod.secret.exs
|
||||||
- mix local.hex --force
|
- mix local.hex --force
|
||||||
- mix local.rebar --force
|
- mix local.rebar --force
|
||||||
script: *release
|
script: *release
|
||||||
|
@ -311,8 +199,9 @@ arm:
|
||||||
artifacts: *release-artifacts
|
artifacts: *release-artifacts
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm32-specified
|
- arm32
|
||||||
image: arm32v7/elixir:1.11.4
|
# TODO: Replace with upstream image when 1.9.0 comes out
|
||||||
|
image: rinpatch/elixir:1.9.0-rc.0-arm
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release
|
before_script: *before-release
|
||||||
|
@ -323,8 +212,9 @@ arm-musl:
|
||||||
artifacts: *release-artifacts
|
artifacts: *release-artifacts
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm32-specified
|
- arm32
|
||||||
image: arm32v7/elixir:1.11.4-alpine
|
# TODO: Replace with upstream image when 1.9.0 comes out
|
||||||
|
image: rinpatch/elixir:1.9.0-rc.0-arm-alpine
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release-musl
|
before_script: *before-release-musl
|
||||||
|
@ -336,7 +226,8 @@ arm64:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm
|
- arm
|
||||||
image: arm64v8/elixir:1.11.4
|
# TODO: Replace with upstream image when 1.9.0 comes out
|
||||||
|
image: rinpatch/elixir:1.9.0-rc.0-arm64
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release
|
before_script: *before-release
|
||||||
|
@ -348,110 +239,9 @@ arm64-musl:
|
||||||
only: *release-only
|
only: *release-only
|
||||||
tags:
|
tags:
|
||||||
- arm
|
- arm
|
||||||
image: arm64v8/elixir:1.11.4-alpine
|
# TODO: Replace with upstream image when 1.9.0 comes out
|
||||||
|
image: rinpatch/elixir:1.9.0-rc.0-arm64-alpine
|
||||||
cache: *release-cache
|
cache: *release-cache
|
||||||
variables: *release-variables
|
variables: *release-variables
|
||||||
before_script: *before-release-musl
|
before_script: *before-release-musl
|
||||||
script: *release
|
script: *release
|
||||||
|
|
||||||
docker:
|
|
||||||
stage: docker
|
|
||||||
image: docker:latest
|
|
||||||
cache: {}
|
|
||||||
dependencies: []
|
|
||||||
variables: &docker-variables
|
|
||||||
DOCKER_DRIVER: overlay2
|
|
||||||
DOCKER_HOST: unix:///var/run/docker.sock
|
|
||||||
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
|
|
||||||
IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
|
|
||||||
IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest
|
|
||||||
IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:latest-stable
|
|
||||||
DOCKER_BUILDX_URL: https://github.com/docker/buildx/releases/download/v0.6.3/buildx-v0.6.3.linux-amd64
|
|
||||||
DOCKER_BUILDX_HASH: 980e6b9655f971991fbbb5fd6cd19f1672386195
|
|
||||||
before_script: &before-docker
|
|
||||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
|
||||||
- docker pull $IMAGE_TAG_SLUG || true
|
|
||||||
- export CI_JOB_TIMESTAMP=$(date --utc -Iseconds)
|
|
||||||
- export CI_VCS_REF=$CI_COMMIT_SHORT_SHA
|
|
||||||
allow_failure: true
|
|
||||||
script:
|
|
||||||
- mkdir -p /root/.docker/cli-plugins
|
|
||||||
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
|
|
||||||
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
|
|
||||||
- chmod +x ~/.docker/cli-plugins/docker-buildx
|
|
||||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
|
||||||
- docker buildx create --name mbuilder --driver docker-container --use
|
|
||||||
- docker buildx inspect --bootstrap
|
|
||||||
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
|
|
||||||
tags:
|
|
||||||
- dind
|
|
||||||
only:
|
|
||||||
- develop@pleroma/pleroma
|
|
||||||
|
|
||||||
docker-stable:
|
|
||||||
stage: docker
|
|
||||||
image: docker:latest
|
|
||||||
cache: {}
|
|
||||||
dependencies: []
|
|
||||||
variables: *docker-variables
|
|
||||||
before_script: *before-docker
|
|
||||||
allow_failure: true
|
|
||||||
script:
|
|
||||||
- mkdir -p /root/.docker/cli-plugins
|
|
||||||
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
|
|
||||||
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
|
|
||||||
- chmod +x ~/.docker/cli-plugins/docker-buildx
|
|
||||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
|
||||||
- docker buildx create --name mbuilder --driver docker-container --use
|
|
||||||
- docker buildx inspect --bootstrap
|
|
||||||
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
|
|
||||||
tags:
|
|
||||||
- dind
|
|
||||||
only:
|
|
||||||
- stable@pleroma/pleroma
|
|
||||||
|
|
||||||
docker-release:
|
|
||||||
stage: docker
|
|
||||||
image: docker:latest
|
|
||||||
cache: {}
|
|
||||||
dependencies: []
|
|
||||||
variables: *docker-variables
|
|
||||||
before_script: *before-docker
|
|
||||||
allow_failure: true
|
|
||||||
script:
|
|
||||||
script:
|
|
||||||
- mkdir -p /root/.docker/cli-plugins
|
|
||||||
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
|
|
||||||
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
|
|
||||||
- chmod +x ~/.docker/cli-plugins/docker-buildx
|
|
||||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
|
||||||
- docker buildx create --name mbuilder --driver docker-container --use
|
|
||||||
- docker buildx inspect --bootstrap
|
|
||||||
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
|
|
||||||
tags:
|
|
||||||
- dind
|
|
||||||
only:
|
|
||||||
- /^release/.*$/@pleroma/pleroma
|
|
||||||
|
|
||||||
docker-adhoc:
|
|
||||||
stage: docker
|
|
||||||
image: docker:latest
|
|
||||||
cache: {}
|
|
||||||
dependencies: []
|
|
||||||
variables: *docker-variables
|
|
||||||
before_script: *before-docker
|
|
||||||
allow_failure: true
|
|
||||||
script:
|
|
||||||
script:
|
|
||||||
- mkdir -p /root/.docker/cli-plugins
|
|
||||||
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
|
|
||||||
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
|
|
||||||
- chmod +x ~/.docker/cli-plugins/docker-buildx
|
|
||||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
|
||||||
- docker buildx create --name mbuilder --driver docker-container --use
|
|
||||||
- docker buildx inspect --bootstrap
|
|
||||||
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
|
|
||||||
tags:
|
|
||||||
- dind
|
|
||||||
only:
|
|
||||||
- /^build-docker/.*$/@pleroma/pleroma
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
<!--
|
|
||||||
### Precheck
|
|
||||||
|
|
||||||
* For support use https://git.pleroma.social/pleroma/pleroma-support or [community channels](https://git.pleroma.social/pleroma/pleroma#community-channels).
|
|
||||||
* Please do a quick search to ensure no similar bug has been reported before. If the bug has not been addressed after 2 weeks, it's fine to bump it.
|
|
||||||
* Try to ensure that the bug is actually related to the Pleroma backend. For example, if a bug happens in Pleroma-FE but not in Mastodon-FE or mobile clients, it's likely that the bug should be filed in [Pleroma-FE](https://git.pleroma.social/pleroma/pleroma-fe/issues/new) repository.
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Environment
|
|
||||||
|
|
||||||
* Installation type (OTP or From Source):
|
|
||||||
* Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE):
|
|
||||||
* Elixir version (`elixir -v` for from source installations, N/A for OTP):
|
|
||||||
* Operating system:
|
|
||||||
* PostgreSQL version (`psql -V`):
|
|
||||||
|
|
||||||
|
|
||||||
### Bug description
|
|
|
@ -1,8 +0,0 @@
|
||||||
### Release checklist
|
|
||||||
* [ ] Bump version in `mix.exs`
|
|
||||||
* [ ] Compile a changelog
|
|
||||||
* [ ] Create an MR with an announcement to pleroma.social
|
|
||||||
#### post-merge
|
|
||||||
* [ ] Tag the release on the merge commit
|
|
||||||
* [ ] Make the tag into a Gitlab Release™
|
|
||||||
* [ ] Merge `stable` into `develop` (in case the fixes are already in develop, use `git merge -s ours --no-commit` and manually merge the changelogs)
|
|
3
.mailmap
3
.mailmap
|
@ -1,3 +0,0 @@
|
||||||
Ariadne Conill <ariadne@dereferenced.org> <nenolod@dereferenced.org>
|
|
||||||
Ariadne Conill <ariadne@dereferenced.org> <nenolod@gmail.com>
|
|
||||||
rinpatch <rin@patch.cx> <rinpatch@sdf.org>
|
|
395
CC-BY-4.0
395
CC-BY-4.0
|
@ -1,395 +0,0 @@
|
||||||
Attribution 4.0 International
|
|
||||||
|
|
||||||
=======================================================================
|
|
||||||
|
|
||||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
|
||||||
does not provide legal services or legal advice. Distribution of
|
|
||||||
Creative Commons public licenses does not create a lawyer-client or
|
|
||||||
other relationship. Creative Commons makes its licenses and related
|
|
||||||
information available on an "as-is" basis. Creative Commons gives no
|
|
||||||
warranties regarding its licenses, any material licensed under their
|
|
||||||
terms and conditions, or any related information. Creative Commons
|
|
||||||
disclaims all liability for damages resulting from their use to the
|
|
||||||
fullest extent possible.
|
|
||||||
|
|
||||||
Using Creative Commons Public Licenses
|
|
||||||
|
|
||||||
Creative Commons public licenses provide a standard set of terms and
|
|
||||||
conditions that creators and other rights holders may use to share
|
|
||||||
original works of authorship and other material subject to copyright
|
|
||||||
and certain other rights specified in the public license below. The
|
|
||||||
following considerations are for informational purposes only, are not
|
|
||||||
exhaustive, and do not form part of our licenses.
|
|
||||||
|
|
||||||
Considerations for licensors: Our public licenses are
|
|
||||||
intended for use by those authorized to give the public
|
|
||||||
permission to use material in ways otherwise restricted by
|
|
||||||
copyright and certain other rights. Our licenses are
|
|
||||||
irrevocable. Licensors should read and understand the terms
|
|
||||||
and conditions of the license they choose before applying it.
|
|
||||||
Licensors should also secure all rights necessary before
|
|
||||||
applying our licenses so that the public can reuse the
|
|
||||||
material as expected. Licensors should clearly mark any
|
|
||||||
material not subject to the license. This includes other CC-
|
|
||||||
licensed material, or material used under an exception or
|
|
||||||
limitation to copyright. More considerations for licensors:
|
|
||||||
wiki.creativecommons.org/Considerations_for_licensors
|
|
||||||
|
|
||||||
Considerations for the public: By using one of our public
|
|
||||||
licenses, a licensor grants the public permission to use the
|
|
||||||
licensed material under specified terms and conditions. If
|
|
||||||
the licensor's permission is not necessary for any reason--for
|
|
||||||
example, because of any applicable exception or limitation to
|
|
||||||
copyright--then that use is not regulated by the license. Our
|
|
||||||
licenses grant only permissions under copyright and certain
|
|
||||||
other rights that a licensor has authority to grant. Use of
|
|
||||||
the licensed material may still be restricted for other
|
|
||||||
reasons, including because others have copyright or other
|
|
||||||
rights in the material. A licensor may make special requests,
|
|
||||||
such as asking that all changes be marked or described.
|
|
||||||
Although not required by our licenses, you are encouraged to
|
|
||||||
respect those requests where reasonable. More considerations
|
|
||||||
for the public:
|
|
||||||
wiki.creativecommons.org/Considerations_for_licensees
|
|
||||||
|
|
||||||
=======================================================================
|
|
||||||
|
|
||||||
Creative Commons Attribution 4.0 International Public License
|
|
||||||
|
|
||||||
By exercising the Licensed Rights (defined below), You accept and agree
|
|
||||||
to be bound by the terms and conditions of this Creative Commons
|
|
||||||
Attribution 4.0 International Public License ("Public License"). To the
|
|
||||||
extent this Public License may be interpreted as a contract, You are
|
|
||||||
granted the Licensed Rights in consideration of Your acceptance of
|
|
||||||
these terms and conditions, and the Licensor grants You such rights in
|
|
||||||
consideration of benefits the Licensor receives from making the
|
|
||||||
Licensed Material available under these terms and conditions.
|
|
||||||
|
|
||||||
|
|
||||||
Section 1 -- Definitions.
|
|
||||||
|
|
||||||
a. Adapted Material means material subject to Copyright and Similar
|
|
||||||
Rights that is derived from or based upon the Licensed Material
|
|
||||||
and in which the Licensed Material is translated, altered,
|
|
||||||
arranged, transformed, or otherwise modified in a manner requiring
|
|
||||||
permission under the Copyright and Similar Rights held by the
|
|
||||||
Licensor. For purposes of this Public License, where the Licensed
|
|
||||||
Material is a musical work, performance, or sound recording,
|
|
||||||
Adapted Material is always produced where the Licensed Material is
|
|
||||||
synched in timed relation with a moving image.
|
|
||||||
|
|
||||||
b. Adapter's License means the license You apply to Your Copyright
|
|
||||||
and Similar Rights in Your contributions to Adapted Material in
|
|
||||||
accordance with the terms and conditions of this Public License.
|
|
||||||
|
|
||||||
c. Copyright and Similar Rights means copyright and/or similar rights
|
|
||||||
closely related to copyright including, without limitation,
|
|
||||||
performance, broadcast, sound recording, and Sui Generis Database
|
|
||||||
Rights, without regard to how the rights are labeled or
|
|
||||||
categorized. For purposes of this Public License, the rights
|
|
||||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
|
||||||
Rights.
|
|
||||||
|
|
||||||
d. Effective Technological Measures means those measures that, in the
|
|
||||||
absence of proper authority, may not be circumvented under laws
|
|
||||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
|
||||||
Treaty adopted on December 20, 1996, and/or similar international
|
|
||||||
agreements.
|
|
||||||
|
|
||||||
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
|
||||||
any other exception or limitation to Copyright and Similar Rights
|
|
||||||
that applies to Your use of the Licensed Material.
|
|
||||||
|
|
||||||
f. Licensed Material means the artistic or literary work, database,
|
|
||||||
or other material to which the Licensor applied this Public
|
|
||||||
License.
|
|
||||||
|
|
||||||
g. Licensed Rights means the rights granted to You subject to the
|
|
||||||
terms and conditions of this Public License, which are limited to
|
|
||||||
all Copyright and Similar Rights that apply to Your use of the
|
|
||||||
Licensed Material and that the Licensor has authority to license.
|
|
||||||
|
|
||||||
h. Licensor means the individual(s) or entity(ies) granting rights
|
|
||||||
under this Public License.
|
|
||||||
|
|
||||||
i. Share means to provide material to the public by any means or
|
|
||||||
process that requires permission under the Licensed Rights, such
|
|
||||||
as reproduction, public display, public performance, distribution,
|
|
||||||
dissemination, communication, or importation, and to make material
|
|
||||||
available to the public including in ways that members of the
|
|
||||||
public may access the material from a place and at a time
|
|
||||||
individually chosen by them.
|
|
||||||
|
|
||||||
j. Sui Generis Database Rights means rights other than copyright
|
|
||||||
resulting from Directive 96/9/EC of the European Parliament and of
|
|
||||||
the Council of 11 March 1996 on the legal protection of databases,
|
|
||||||
as amended and/or succeeded, as well as other essentially
|
|
||||||
equivalent rights anywhere in the world.
|
|
||||||
|
|
||||||
k. You means the individual or entity exercising the Licensed Rights
|
|
||||||
under this Public License. Your has a corresponding meaning.
|
|
||||||
|
|
||||||
|
|
||||||
Section 2 -- Scope.
|
|
||||||
|
|
||||||
a. License grant.
|
|
||||||
|
|
||||||
1. Subject to the terms and conditions of this Public License,
|
|
||||||
the Licensor hereby grants You a worldwide, royalty-free,
|
|
||||||
non-sublicensable, non-exclusive, irrevocable license to
|
|
||||||
exercise the Licensed Rights in the Licensed Material to:
|
|
||||||
|
|
||||||
a. reproduce and Share the Licensed Material, in whole or
|
|
||||||
in part; and
|
|
||||||
|
|
||||||
b. produce, reproduce, and Share Adapted Material.
|
|
||||||
|
|
||||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
|
||||||
Exceptions and Limitations apply to Your use, this Public
|
|
||||||
License does not apply, and You do not need to comply with
|
|
||||||
its terms and conditions.
|
|
||||||
|
|
||||||
3. Term. The term of this Public License is specified in Section
|
|
||||||
6(a).
|
|
||||||
|
|
||||||
4. Media and formats; technical modifications allowed. The
|
|
||||||
Licensor authorizes You to exercise the Licensed Rights in
|
|
||||||
all media and formats whether now known or hereafter created,
|
|
||||||
and to make technical modifications necessary to do so. The
|
|
||||||
Licensor waives and/or agrees not to assert any right or
|
|
||||||
authority to forbid You from making technical modifications
|
|
||||||
necessary to exercise the Licensed Rights, including
|
|
||||||
technical modifications necessary to circumvent Effective
|
|
||||||
Technological Measures. For purposes of this Public License,
|
|
||||||
simply making modifications authorized by this Section 2(a)
|
|
||||||
(4) never produces Adapted Material.
|
|
||||||
|
|
||||||
5. Downstream recipients.
|
|
||||||
|
|
||||||
a. Offer from the Licensor -- Licensed Material. Every
|
|
||||||
recipient of the Licensed Material automatically
|
|
||||||
receives an offer from the Licensor to exercise the
|
|
||||||
Licensed Rights under the terms and conditions of this
|
|
||||||
Public License.
|
|
||||||
|
|
||||||
b. No downstream restrictions. You may not offer or impose
|
|
||||||
any additional or different terms or conditions on, or
|
|
||||||
apply any Effective Technological Measures to, the
|
|
||||||
Licensed Material if doing so restricts exercise of the
|
|
||||||
Licensed Rights by any recipient of the Licensed
|
|
||||||
Material.
|
|
||||||
|
|
||||||
6. No endorsement. Nothing in this Public License constitutes or
|
|
||||||
may be construed as permission to assert or imply that You
|
|
||||||
are, or that Your use of the Licensed Material is, connected
|
|
||||||
with, or sponsored, endorsed, or granted official status by,
|
|
||||||
the Licensor or others designated to receive attribution as
|
|
||||||
provided in Section 3(a)(1)(A)(i).
|
|
||||||
|
|
||||||
b. Other rights.
|
|
||||||
|
|
||||||
1. Moral rights, such as the right of integrity, are not
|
|
||||||
licensed under this Public License, nor are publicity,
|
|
||||||
privacy, and/or other similar personality rights; however, to
|
|
||||||
the extent possible, the Licensor waives and/or agrees not to
|
|
||||||
assert any such rights held by the Licensor to the limited
|
|
||||||
extent necessary to allow You to exercise the Licensed
|
|
||||||
Rights, but not otherwise.
|
|
||||||
|
|
||||||
2. Patent and trademark rights are not licensed under this
|
|
||||||
Public License.
|
|
||||||
|
|
||||||
3. To the extent possible, the Licensor waives any right to
|
|
||||||
collect royalties from You for the exercise of the Licensed
|
|
||||||
Rights, whether directly or through a collecting society
|
|
||||||
under any voluntary or waivable statutory or compulsory
|
|
||||||
licensing scheme. In all other cases the Licensor expressly
|
|
||||||
reserves any right to collect such royalties.
|
|
||||||
|
|
||||||
|
|
||||||
Section 3 -- License Conditions.
|
|
||||||
|
|
||||||
Your exercise of the Licensed Rights is expressly made subject to the
|
|
||||||
following conditions.
|
|
||||||
|
|
||||||
a. Attribution.
|
|
||||||
|
|
||||||
1. If You Share the Licensed Material (including in modified
|
|
||||||
form), You must:
|
|
||||||
|
|
||||||
a. retain the following if it is supplied by the Licensor
|
|
||||||
with the Licensed Material:
|
|
||||||
|
|
||||||
i. identification of the creator(s) of the Licensed
|
|
||||||
Material and any others designated to receive
|
|
||||||
attribution, in any reasonable manner requested by
|
|
||||||
the Licensor (including by pseudonym if
|
|
||||||
designated);
|
|
||||||
|
|
||||||
ii. a copyright notice;
|
|
||||||
|
|
||||||
iii. a notice that refers to this Public License;
|
|
||||||
|
|
||||||
iv. a notice that refers to the disclaimer of
|
|
||||||
warranties;
|
|
||||||
|
|
||||||
v. a URI or hyperlink to the Licensed Material to the
|
|
||||||
extent reasonably practicable;
|
|
||||||
|
|
||||||
b. indicate if You modified the Licensed Material and
|
|
||||||
retain an indication of any previous modifications; and
|
|
||||||
|
|
||||||
c. indicate the Licensed Material is licensed under this
|
|
||||||
Public License, and include the text of, or the URI or
|
|
||||||
hyperlink to, this Public License.
|
|
||||||
|
|
||||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
|
||||||
reasonable manner based on the medium, means, and context in
|
|
||||||
which You Share the Licensed Material. For example, it may be
|
|
||||||
reasonable to satisfy the conditions by providing a URI or
|
|
||||||
hyperlink to a resource that includes the required
|
|
||||||
information.
|
|
||||||
|
|
||||||
3. If requested by the Licensor, You must remove any of the
|
|
||||||
information required by Section 3(a)(1)(A) to the extent
|
|
||||||
reasonably practicable.
|
|
||||||
|
|
||||||
4. If You Share Adapted Material You produce, the Adapter's
|
|
||||||
License You apply must not prevent recipients of the Adapted
|
|
||||||
Material from complying with this Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Section 4 -- Sui Generis Database Rights.
|
|
||||||
|
|
||||||
Where the Licensed Rights include Sui Generis Database Rights that
|
|
||||||
apply to Your use of the Licensed Material:
|
|
||||||
|
|
||||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
|
||||||
to extract, reuse, reproduce, and Share all or a substantial
|
|
||||||
portion of the contents of the database;
|
|
||||||
|
|
||||||
b. if You include all or a substantial portion of the database
|
|
||||||
contents in a database in which You have Sui Generis Database
|
|
||||||
Rights, then the database in which You have Sui Generis Database
|
|
||||||
Rights (but not its individual contents) is Adapted Material; and
|
|
||||||
|
|
||||||
c. You must comply with the conditions in Section 3(a) if You Share
|
|
||||||
all or a substantial portion of the contents of the database.
|
|
||||||
|
|
||||||
For the avoidance of doubt, this Section 4 supplements and does not
|
|
||||||
replace Your obligations under this Public License where the Licensed
|
|
||||||
Rights include other Copyright and Similar Rights.
|
|
||||||
|
|
||||||
|
|
||||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
|
||||||
|
|
||||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
|
||||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
|
||||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
|
||||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
|
||||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
|
||||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
|
||||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
|
||||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
|
||||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
|
||||||
|
|
||||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
|
||||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
|
||||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
|
||||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
|
||||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
|
||||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
|
||||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
|
||||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
|
||||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
|
||||||
|
|
||||||
c. The disclaimer of warranties and limitation of liability provided
|
|
||||||
above shall be interpreted in a manner that, to the extent
|
|
||||||
possible, most closely approximates an absolute disclaimer and
|
|
||||||
waiver of all liability.
|
|
||||||
|
|
||||||
|
|
||||||
Section 6 -- Term and Termination.
|
|
||||||
|
|
||||||
a. This Public License applies for the term of the Copyright and
|
|
||||||
Similar Rights licensed here. However, if You fail to comply with
|
|
||||||
this Public License, then Your rights under this Public License
|
|
||||||
terminate automatically.
|
|
||||||
|
|
||||||
b. Where Your right to use the Licensed Material has terminated under
|
|
||||||
Section 6(a), it reinstates:
|
|
||||||
|
|
||||||
1. automatically as of the date the violation is cured, provided
|
|
||||||
it is cured within 30 days of Your discovery of the
|
|
||||||
violation; or
|
|
||||||
|
|
||||||
2. upon express reinstatement by the Licensor.
|
|
||||||
|
|
||||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
|
||||||
right the Licensor may have to seek remedies for Your violations
|
|
||||||
of this Public License.
|
|
||||||
|
|
||||||
c. For the avoidance of doubt, the Licensor may also offer the
|
|
||||||
Licensed Material under separate terms or conditions or stop
|
|
||||||
distributing the Licensed Material at any time; however, doing so
|
|
||||||
will not terminate this Public License.
|
|
||||||
|
|
||||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
|
||||||
License.
|
|
||||||
|
|
||||||
|
|
||||||
Section 7 -- Other Terms and Conditions.
|
|
||||||
|
|
||||||
a. The Licensor shall not be bound by any additional or different
|
|
||||||
terms or conditions communicated by You unless expressly agreed.
|
|
||||||
|
|
||||||
b. Any arrangements, understandings, or agreements regarding the
|
|
||||||
Licensed Material not stated herein are separate from and
|
|
||||||
independent of the terms and conditions of this Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Section 8 -- Interpretation.
|
|
||||||
|
|
||||||
a. For the avoidance of doubt, this Public License does not, and
|
|
||||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
|
||||||
conditions on any use of the Licensed Material that could lawfully
|
|
||||||
be made without permission under this Public License.
|
|
||||||
|
|
||||||
b. To the extent possible, if any provision of this Public License is
|
|
||||||
deemed unenforceable, it shall be automatically reformed to the
|
|
||||||
minimum extent necessary to make it enforceable. If the provision
|
|
||||||
cannot be reformed, it shall be severed from this Public License
|
|
||||||
without affecting the enforceability of the remaining terms and
|
|
||||||
conditions.
|
|
||||||
|
|
||||||
c. No term or condition of this Public License will be waived and no
|
|
||||||
failure to comply consented to unless expressly agreed to by the
|
|
||||||
Licensor.
|
|
||||||
|
|
||||||
d. Nothing in this Public License constitutes or may be interpreted
|
|
||||||
as a limitation upon, or waiver of, any privileges and immunities
|
|
||||||
that apply to the Licensor or You, including from the legal
|
|
||||||
processes of any jurisdiction or authority.
|
|
||||||
|
|
||||||
|
|
||||||
=======================================================================
|
|
||||||
|
|
||||||
Creative Commons is not a party to its public
|
|
||||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
|
||||||
its public licenses to material it publishes and in those instances
|
|
||||||
will be considered the “Licensor.” The text of the Creative Commons
|
|
||||||
public licenses is dedicated to the public domain under the CC0 Public
|
|
||||||
Domain Dedication. Except for the limited purpose of indicating that
|
|
||||||
material is shared under a Creative Commons public license or as
|
|
||||||
otherwise permitted by the Creative Commons policies published at
|
|
||||||
creativecommons.org/policies, Creative Commons does not authorize the
|
|
||||||
use of the trademark "Creative Commons" or any other trademark or logo
|
|
||||||
of Creative Commons without its prior written consent including,
|
|
||||||
without limitation, in connection with any unauthorized modifications
|
|
||||||
to any of its public licenses or any other arrangements,
|
|
||||||
understandings, or agreements concerning use of licensed material. For
|
|
||||||
the avoidance of doubt, this paragraph does not form part of the
|
|
||||||
public licenses.
|
|
||||||
|
|
||||||
Creative Commons may be contacted at creativecommons.org.
|
|
1050
CHANGELOG.md
1050
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
11
COPYING
11
COPYING
|
@ -1,17 +1,10 @@
|
||||||
Unless otherwise stated this repository is copyright © 2017-2022
|
Unless otherwise stated this repository is copyright © 2017-2019
|
||||||
Pleroma Authors <https://pleroma.social/>, and is distributed under
|
Pleroma Authors <https://pleroma.social/>, and is distributed under
|
||||||
The GNU Affero General Public License Version 3, you should have received a
|
The GNU Affero General Public License Version 3, you should have received a
|
||||||
copy of the license file as AGPL-3.
|
copy of the license file as AGPL-3.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Files inside docs directory are copyright © 2022 Pleroma Authors
|
|
||||||
<https://pleroma.social/>, and are distributed under the Creative Commons
|
|
||||||
Attribution 4.0 International license, you should have received
|
|
||||||
a copy of the license file as CC-BY-4.0.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
The following files are copyright © 2019 shitposter.club, and are distributed
|
The following files are copyright © 2019 shitposter.club, and are distributed
|
||||||
under the Creative Commons Attribution-ShareAlike 4.0 International license,
|
under the Creative Commons Attribution-ShareAlike 4.0 International license,
|
||||||
you should have received a copy of the license file as CC-BY-SA-4.0.
|
you should have received a copy of the license file as CC-BY-SA-4.0.
|
||||||
|
@ -30,7 +23,7 @@ priv/static/images/pleroma-fox-tan-shy.png
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
The following files are copyright © 2017-2022 Pleroma Authors
|
The following files are copyright © 2017-2019 Pleroma Authors
|
||||||
<https://pleroma.social/>, and are distributed under the Creative Commons
|
<https://pleroma.social/>, and are distributed under the Creative Commons
|
||||||
Attribution-ShareAlike 4.0 International license, you should have received
|
Attribution-ShareAlike 4.0 International license, you should have received
|
||||||
a copy of the license file as CC-BY-SA-4.0.
|
a copy of the license file as CC-BY-SA-4.0.
|
||||||
|
|
52
Dockerfile
52
Dockerfile
|
@ -1,52 +0,0 @@
|
||||||
FROM elixir:1.11.4-alpine as build
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
ENV MIX_ENV=prod
|
|
||||||
|
|
||||||
RUN apk add git gcc g++ musl-dev make cmake file-dev &&\
|
|
||||||
echo "import Config" > config/prod.secret.exs &&\
|
|
||||||
mix local.hex --force &&\
|
|
||||||
mix local.rebar --force &&\
|
|
||||||
mix deps.get --only prod &&\
|
|
||||||
mkdir release &&\
|
|
||||||
mix release --path release
|
|
||||||
|
|
||||||
FROM alpine
|
|
||||||
|
|
||||||
ARG BUILD_DATE
|
|
||||||
ARG VCS_REF
|
|
||||||
|
|
||||||
LABEL maintainer="ops@pleroma.social" \
|
|
||||||
org.opencontainers.image.title="pleroma" \
|
|
||||||
org.opencontainers.image.description="Pleroma for Docker" \
|
|
||||||
org.opencontainers.image.authors="ops@pleroma.social" \
|
|
||||||
org.opencontainers.image.vendor="pleroma.social" \
|
|
||||||
org.opencontainers.image.documentation="https://git.pleroma.social/pleroma/pleroma" \
|
|
||||||
org.opencontainers.image.licenses="AGPL-3.0" \
|
|
||||||
org.opencontainers.image.url="https://pleroma.social" \
|
|
||||||
org.opencontainers.image.revision=$VCS_REF \
|
|
||||||
org.opencontainers.image.created=$BUILD_DATE
|
|
||||||
|
|
||||||
ARG HOME=/opt/pleroma
|
|
||||||
ARG DATA=/var/lib/pleroma
|
|
||||||
|
|
||||||
RUN apk update &&\
|
|
||||||
apk add exiftool ffmpeg imagemagick libmagic ncurses postgresql-client &&\
|
|
||||||
adduser --system --shell /bin/false --home ${HOME} pleroma &&\
|
|
||||||
mkdir -p ${DATA}/uploads &&\
|
|
||||||
mkdir -p ${DATA}/static &&\
|
|
||||||
chown -R pleroma ${DATA} &&\
|
|
||||||
mkdir -p /etc/pleroma &&\
|
|
||||||
chown -R pleroma /etc/pleroma
|
|
||||||
|
|
||||||
USER pleroma
|
|
||||||
|
|
||||||
COPY --from=build --chown=pleroma:0 /release ${HOME}
|
|
||||||
|
|
||||||
COPY ./config/docker.exs /etc/pleroma/config.exs
|
|
||||||
COPY ./docker-entrypoint.sh ${HOME}
|
|
||||||
|
|
||||||
EXPOSE 4000
|
|
||||||
|
|
||||||
ENTRYPOINT ["/opt/pleroma/docker-entrypoint.sh"]
|
|
103
README.md
103
README.md
|
@ -1,57 +1,80 @@
|
||||||
<img src="https://git.pleroma.social/pleroma/pleroma/uploads/8cec84f5a084d887339f57deeb8a293e/pleroma-banner-vector-nopad-notext.svg" width="300px" />
|
# Pleroma
|
||||||
|
|
||||||
## About
|
**Note**: This readme as well as complete documentation is also available at <https://docs-develop.pleroma.social>
|
||||||
|
|
||||||
Pleroma is a microblogging server software that can federate (= exchange messages with) other servers that support ActivityPub. What that means is that you can host a server for yourself or your friends and stay in control of your online identity, but still exchange messages with people on larger servers. Pleroma will federate with all servers that implement ActivityPub, like Friendica, GNU Social, Hubzilla, Mastodon, Misskey, Peertube, and Pixelfed.
|
## About Pleroma
|
||||||
|
|
||||||
Pleroma is written in Elixir and uses PostgresSQL for data storage. It's efficient enough to be ran on low-power devices like Raspberry Pi (though we wouldn't recommend storing the database on the internal SD card ;) but can scale well when ran on more powerful hardware (albeit only single-node for now).
|
Pleroma is a microblogging server software that can federate (= exchange messages with) other servers that support the same federation standards (OStatus and ActivityPub). What that means is that you can host a server for yourself or your friends and stay in control of your online identity, but still exchange messages with people on larger servers. Pleroma will federate with all servers that implement either OStatus or ActivityPub, like Friendica, GNU Social, Hubzilla, Mastodon, Misskey, Peertube, and Pixelfed.
|
||||||
|
|
||||||
For clients it supports the [Mastodon client API](https://docs.joinmastodon.org/api/guidelines/) with Pleroma extensions (see the API section on <https://docs-develop.pleroma.social>).
|
Pleroma is written in Elixir, high-performance and can run on small devices like a Raspberry Pi.
|
||||||
|
|
||||||
- [Client Applications for Pleroma](https://docs-develop.pleroma.social/backend/clients/)
|
For clients it supports both the [GNU Social API with Qvitter extensions](https://twitter-api.readthedocs.io/en/latest/index.html) and the [Mastodon client API](https://docs.joinmastodon.org/api/guidelines/).
|
||||||
|
|
||||||
|
- [Client Applications for Pleroma](https://docs-develop.pleroma.social/clients.html)
|
||||||
|
|
||||||
|
If you want to run your own server, feel free to contact us at @lain@pleroma.soykaf.com or in our dev chat at #pleroma on freenode or via matrix at <https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org>.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
**Note:** The guide below may be outdated and in most cases shouldn't be used. Instead check out our [wiki](https://docs.pleroma.social) for platform-specific installation instructions, most likely [Installing on Linux using OTP releases](https://docs.pleroma.social/otp_en.html) is the guide you need.
|
||||||
### OTP releases (Recommended)
|
|
||||||
If you are running Linux (glibc or musl) on x86/arm, the recommended way to install Pleroma is by using OTP releases. OTP releases are as close as you can get to binary releases with Erlang/Elixir. The release is self-contained, and provides everything needed to boot it. The installation instructions are available [here](https://docs-develop.pleroma.social/backend/installation/otp_en/).
|
|
||||||
|
|
||||||
### From Source
|
|
||||||
If your platform is not supported, or you just want to be able to edit the source code easily, you may install Pleroma from source.
|
|
||||||
|
|
||||||
- [Alpine Linux](https://docs-develop.pleroma.social/backend/installation/alpine_linux_en/)
|
|
||||||
- [Arch Linux](https://docs-develop.pleroma.social/backend/installation/arch_linux_en/)
|
|
||||||
- [CentOS 7](https://docs-develop.pleroma.social/backend/installation/centos7_en/)
|
|
||||||
- [Debian-based](https://docs-develop.pleroma.social/backend/installation/debian_based_en/)
|
|
||||||
- [Debian-based (jp)](https://docs-develop.pleroma.social/backend/installation/debian_based_jp/)
|
|
||||||
- [FreeBSD](https://docs-develop.pleroma.social/backend/installation/freebsd_en/)
|
|
||||||
- [Gentoo Linux](https://docs-develop.pleroma.social/backend/installation/gentoo_en/)
|
|
||||||
- [NetBSD](https://docs-develop.pleroma.social/backend/installation/netbsd_en/)
|
|
||||||
- [OpenBSD](https://docs-develop.pleroma.social/backend/installation/openbsd_en/)
|
|
||||||
- [OpenBSD (fi)](https://docs-develop.pleroma.social/backend/installation/openbsd_fi/)
|
|
||||||
|
|
||||||
### OS/Distro packages
|
### OS/Distro packages
|
||||||
Currently Pleroma is packaged for [YunoHost](https://yunohost.org) and [NixOS](https://nixos.org). If you want to package Pleroma for any OS/Distros, we can guide you through the process on our [community channels](#community-channels). If you want to change default options in your Pleroma package, please **discuss it with us first**.
|
Currently Pleroma is not packaged by any OS/Distros, but feel free to reach out to us at [#pleroma-dev on freenode](https://webchat.freenode.net/?channels=%23pleroma-dev) or via matrix at <https://matrix.heldscal.la/#/room/#freenode_#pleroma-dev:matrix.org> for assistance. If you want to change default options in your Pleroma package, please **discuss it with us first**.
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
While we don’t provide docker files, other people have written very good ones. Take a look at <https://github.com/angristan/docker-pleroma> or <https://glitch.sh/sn0w/pleroma-docker>.
|
While we don’t provide docker files, other people have written very good ones. Take a look at <https://github.com/angristan/docker-pleroma> or <https://github.com/sn0w/pleroma-docker>.
|
||||||
|
|
||||||
### Raspberry Pi
|
### Dependencies
|
||||||
Community maintained Raspberry Pi image that you can flash and run Pleroma on your Raspberry Pi. Available here <https://github.com/guysoft/PleromaPi>.
|
|
||||||
|
|
||||||
### Compilation Troubleshooting
|
* Postgresql version 9.6 or newer
|
||||||
If you ever encounter compilation issues during the updating of Pleroma, you can try these commands and see if they fix things:
|
* Elixir version 1.7 or newer. If your distribution only has an old version available, check [Elixir’s install page](https://elixir-lang.org/install.html) or use a tool like [asdf](https://github.com/asdf-vm/asdf).
|
||||||
|
* Build-essential tools
|
||||||
|
|
||||||
- `mix deps.clean --all`
|
### Configuration
|
||||||
- `mix local.rebar`
|
|
||||||
- `mix local.hex`
|
|
||||||
- `rm -r _build`
|
|
||||||
|
|
||||||
If you are not developing Pleroma, it is better to use the OTP release, which comes with everything precompiled.
|
* Run `mix deps.get` to install elixir dependencies.
|
||||||
|
* Run `mix pleroma.instance gen`. This will ask you questions about your instance and generate a configuration file in `config/generated_config.exs`. Check that and copy it to either `config/dev.secret.exs` or `config/prod.secret.exs`. It will also create a `config/setup_db.psql`, which you should run as the PostgreSQL superuser (i.e., `sudo -u postgres psql -f config/setup_db.psql`). It will create the database, user, and password you gave `mix pleroma.gen.instance` earlier, as well as set up the necessary extensions in the database. PostgreSQL superuser privileges are only needed for this step.
|
||||||
|
* For these next steps, the default will be to run pleroma using the dev configuration file, `config/dev.secret.exs`. To run them using the prod config file, prefix each command at the shell with `MIX_ENV=prod`. For example: `MIX_ENV=prod mix phx.server`. Documentation for the config can be found at [`docs/config.md`](docs/config.md) in the repository, or at the "Configuration" page on <https://docs-develop.pleroma.social/config.html>
|
||||||
|
* Run `mix ecto.migrate` to run the database migrations. You will have to do this again after certain updates.
|
||||||
|
* You can check if your instance is configured correctly by running it with `mix phx.server` and checking the instance info endpoint at `/api/v1/instance`. If it shows your uri, name and email correctly, you are configured correctly. If it shows something like `localhost:4000`, your configuration is probably wrong, unless you are running a local development setup.
|
||||||
|
* The common and convenient way for adding HTTPS is by using Nginx as a reverse proxy. You can look at example Nginx configuration in `installation/pleroma.nginx`. If you need TLS/SSL certificates for HTTPS, you can look get some for free with letsencrypt: <https://letsencrypt.org/>. The simplest way to obtain and install a certificate is to use [Certbot.](https://certbot.eff.org) Depending on your specific setup, certbot may be able to get a certificate and configure your web server automatically.
|
||||||
|
|
||||||
## Documentation
|
## Running
|
||||||
- Latest Released revision: <https://docs.pleroma.social>
|
|
||||||
- Latest Git revision: <https://docs-develop.pleroma.social>
|
|
||||||
|
|
||||||
## Community Channels
|
* By default, it listens on port 4000 (TCP), so you can access it on <http://localhost:4000/> (if you are on the same machine). In case of an error it will restart automatically.
|
||||||
* IRC: **#pleroma** and **#pleroma-dev** on libera.chat, webchat is available at <https://irc.pleroma.social>
|
|
||||||
* Matrix: [#pleroma:libera.chat](https://matrix.to/#/#pleroma:libera.chat) and [#pleroma-dev:libera.chat](https://matrix.to/#/#pleroma-dev:libera.chat)
|
### Frontends
|
||||||
|
|
||||||
|
Pleroma comes with two frontends. The first one, Pleroma FE, can be reached by normally visiting the site. The other one, based on the Mastodon project, can be found by visiting the /web path of your site.
|
||||||
|
|
||||||
|
### As systemd service (with provided .service file)
|
||||||
|
|
||||||
|
Example .service file can be found in `installation/pleroma.service`. Copy this to `/etc/systemd/system/`. Running `systemctl enable --now pleroma.service` will run Pleroma and enable startup on boot. Logs can be watched by using `journalctl -fu pleroma.service`.
|
||||||
|
|
||||||
|
### As OpenRC service (with provided RC file)
|
||||||
|
|
||||||
|
Copy `installation/init.d/pleroma` to `/etc/init.d/pleroma`. You can add it to the services ran by default with: `rc-update add pleroma`
|
||||||
|
|
||||||
|
### Standalone/run by other means
|
||||||
|
|
||||||
|
Run `mix phx.server` in repository’s root, it will output log into stdout/stderr.
|
||||||
|
|
||||||
|
### Using an upstream proxy for federation
|
||||||
|
|
||||||
|
Add the following to your `dev.secret.exs` or `prod.secret.exs` if you want to proxify all http requests that Pleroma makes to an upstream proxy server:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :http,
|
||||||
|
proxy_url: "127.0.0.1:8123"
|
||||||
|
```
|
||||||
|
|
||||||
|
This is useful for running Pleroma inside Tor or I2P.
|
||||||
|
|
||||||
|
## Customization and contribution
|
||||||
|
|
||||||
|
The [Pleroma Documentation](https://docs-develop.pleroma.social/readme.html) offers manuals and guides on how to further customize your instance to your liking and how you can contribute to the project.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### No incoming federation
|
||||||
|
|
||||||
|
Check that you correctly forward the `host` header to the backend. It is needed to validate signatures.
|
||||||
|
|
16
SECURITY.md
16
SECURITY.md
|
@ -1,16 +0,0 @@
|
||||||
# Pleroma backend security policy
|
|
||||||
|
|
||||||
## Supported versions
|
|
||||||
|
|
||||||
Currently, Pleroma offers bugfixes and security patches only for the latest minor release.
|
|
||||||
|
|
||||||
| Version | Support
|
|
||||||
|---------| --------
|
|
||||||
| 2.2 | Bugfixes and security patches
|
|
||||||
|
|
||||||
## Reporting a vulnerability
|
|
||||||
|
|
||||||
Please use confidential issues (tick the "This issue is confidential and should only be visible to team members with at least Reporter access." box when submitting) at our [bugtracker](https://git.pleroma.social/pleroma/pleroma/-/issues/new) for reporting vulnerabilities.
|
|
||||||
## Announcements
|
|
||||||
|
|
||||||
New releases are announced at [pleroma.social](https://pleroma.social/announcements/). All security releases are tagged with ["Security"](https://pleroma.social/announcements/tags/security/). You can be notified of them by subscribing to an Atom feed at <https://pleroma.social/announcements/tags/security/feed.xml>.
|
|
|
@ -1,595 +0,0 @@
|
||||||
defmodule Pleroma.LoadTesting.Activities do
|
|
||||||
@moduledoc """
|
|
||||||
Module for generating different activities.
|
|
||||||
"""
|
|
||||||
import Ecto.Query
|
|
||||||
import Pleroma.LoadTesting.Helper, only: [to_sec: 1]
|
|
||||||
|
|
||||||
alias Ecto.UUID
|
|
||||||
alias Pleroma.Constants
|
|
||||||
alias Pleroma.LoadTesting.Users
|
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.Web.CommonAPI
|
|
||||||
|
|
||||||
require Constants
|
|
||||||
|
|
||||||
@defaults [
|
|
||||||
iterations: 170,
|
|
||||||
friends_used: 20,
|
|
||||||
non_friends_used: 20
|
|
||||||
]
|
|
||||||
|
|
||||||
@max_concurrency 10
|
|
||||||
|
|
||||||
@visibility ~w(public private direct unlisted)
|
|
||||||
@types [
|
|
||||||
:simple,
|
|
||||||
:simple_filtered,
|
|
||||||
:emoji,
|
|
||||||
:mentions,
|
|
||||||
:hell_thread,
|
|
||||||
:attachment,
|
|
||||||
:tag,
|
|
||||||
:like,
|
|
||||||
:reblog,
|
|
||||||
:simple_thread
|
|
||||||
]
|
|
||||||
@groups [:friends_local, :friends_remote, :non_friends_local, :non_friends_local]
|
|
||||||
@remote_groups [:friends_remote, :non_friends_remote]
|
|
||||||
@friends_groups [:friends_local, :friends_remote]
|
|
||||||
@non_friends_groups [:non_friends_local, :non_friends_remote]
|
|
||||||
|
|
||||||
@spec generate(User.t(), keyword()) :: :ok
|
|
||||||
def generate(user, opts \\ []) do
|
|
||||||
{:ok, _} =
|
|
||||||
Agent.start_link(fn -> %{} end,
|
|
||||||
name: :benchmark_state
|
|
||||||
)
|
|
||||||
|
|
||||||
opts = Keyword.merge(@defaults, opts)
|
|
||||||
|
|
||||||
users = Users.prepare_users(user, opts)
|
|
||||||
|
|
||||||
{:ok, _} = Agent.start_link(fn -> users[:non_friends_remote] end, name: :non_friends_remote)
|
|
||||||
|
|
||||||
task_data =
|
|
||||||
for visibility <- @visibility,
|
|
||||||
type <- @types,
|
|
||||||
group <- [:user | @groups],
|
|
||||||
do: {visibility, type, group}
|
|
||||||
|
|
||||||
IO.puts("Starting generating #{opts[:iterations]} iterations of activities...")
|
|
||||||
|
|
||||||
public_long_thread = fn ->
|
|
||||||
generate_long_thread("public", users, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
private_long_thread = fn ->
|
|
||||||
generate_long_thread("private", users, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
iterations = opts[:iterations]
|
|
||||||
|
|
||||||
{time, _} =
|
|
||||||
:timer.tc(fn ->
|
|
||||||
Enum.each(
|
|
||||||
1..iterations,
|
|
||||||
fn
|
|
||||||
i when i == iterations - 2 ->
|
|
||||||
spawn(public_long_thread)
|
|
||||||
spawn(private_long_thread)
|
|
||||||
generate_activities(users, Enum.shuffle(task_data), opts)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
generate_activities(users, Enum.shuffle(task_data), opts)
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end)
|
|
||||||
|
|
||||||
IO.puts("Generating iterations of activities took #{to_sec(time)} sec.\n")
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_power_intervals(opts \\ []) do
|
|
||||||
count = Keyword.get(opts, :count, 20)
|
|
||||||
power = Keyword.get(opts, :power, 2)
|
|
||||||
IO.puts("Generating #{count} intervals for a power #{power} series...")
|
|
||||||
counts = Enum.map(1..count, fn n -> :math.pow(n, power) end)
|
|
||||||
sum = Enum.sum(counts)
|
|
||||||
|
|
||||||
densities =
|
|
||||||
Enum.map(counts, fn c ->
|
|
||||||
c / sum
|
|
||||||
end)
|
|
||||||
|
|
||||||
densities
|
|
||||||
|> Enum.reduce(0, fn density, acc ->
|
|
||||||
if acc == 0 do
|
|
||||||
[{0, density}]
|
|
||||||
else
|
|
||||||
[{_, lower} | _] = acc
|
|
||||||
[{lower, lower + density} | acc]
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> Enum.reverse()
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_tagged_activities(opts \\ []) do
|
|
||||||
tag_count = Keyword.get(opts, :tag_count, 20)
|
|
||||||
users = Keyword.get(opts, :users, Repo.all(Pleroma.User))
|
|
||||||
activity_count = Keyword.get(opts, :count, 200_000)
|
|
||||||
|
|
||||||
intervals = generate_power_intervals(count: tag_count)
|
|
||||||
|
|
||||||
IO.puts(
|
|
||||||
"Generating #{activity_count} activities using #{tag_count} different tags of format `tag_n`, starting at tag_0"
|
|
||||||
)
|
|
||||||
|
|
||||||
Enum.each(1..activity_count, fn _ ->
|
|
||||||
random = :rand.uniform()
|
|
||||||
i = Enum.find_index(intervals, fn {lower, upper} -> lower <= random && upper > random end)
|
|
||||||
CommonAPI.post(Enum.random(users), %{status: "a post with the tag #tag_#{i}"})
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp generate_long_thread(visibility, users, _opts) do
|
|
||||||
group =
|
|
||||||
if visibility == "public",
|
|
||||||
do: :friends_local,
|
|
||||||
else: :user
|
|
||||||
|
|
||||||
tasks = get_reply_tasks(visibility, group) |> Stream.cycle() |> Enum.take(50)
|
|
||||||
|
|
||||||
{:ok, activity} =
|
|
||||||
CommonAPI.post(users[:user], %{
|
|
||||||
status: "Start of #{visibility} long thread",
|
|
||||||
visibility: visibility
|
|
||||||
})
|
|
||||||
|
|
||||||
Agent.update(:benchmark_state, fn state ->
|
|
||||||
key =
|
|
||||||
if visibility == "public",
|
|
||||||
do: :public_thread,
|
|
||||||
else: :private_thread
|
|
||||||
|
|
||||||
Map.put(state, key, activity)
|
|
||||||
end)
|
|
||||||
|
|
||||||
acc = {activity.id, ["@" <> users[:user].nickname, "reply to long thread"]}
|
|
||||||
insert_replies_for_long_thread(tasks, visibility, users, acc)
|
|
||||||
IO.puts("Generating #{visibility} long thread ended\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_replies_for_long_thread(tasks, visibility, users, acc) do
|
|
||||||
Enum.reduce(tasks, acc, fn
|
|
||||||
:user, {id, data} ->
|
|
||||||
user = users[:user]
|
|
||||||
insert_reply(user, List.delete(data, "@" <> user.nickname), id, visibility)
|
|
||||||
|
|
||||||
group, {id, data} ->
|
|
||||||
replier = Enum.random(users[group])
|
|
||||||
insert_reply(replier, List.delete(data, "@" <> replier.nickname), id, visibility)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp generate_activities(users, task_data, opts) do
|
|
||||||
Task.async_stream(
|
|
||||||
task_data,
|
|
||||||
fn {visibility, type, group} ->
|
|
||||||
insert_activity(type, visibility, group, users, opts)
|
|
||||||
end,
|
|
||||||
max_concurrency: @max_concurrency,
|
|
||||||
timeout: 30_000
|
|
||||||
)
|
|
||||||
|> Stream.run()
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_local_activity(visibility, group, users, status) do
|
|
||||||
{:ok, _} =
|
|
||||||
group
|
|
||||||
|> get_actor(users)
|
|
||||||
|> CommonAPI.post(%{status: status, visibility: visibility})
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_remote_activity(visibility, group, users, status) do
|
|
||||||
actor = get_actor(group, users)
|
|
||||||
{act_data, obj_data} = prepare_activity_data(actor, visibility, users[:user])
|
|
||||||
{activity_data, object_data} = other_data(actor, status)
|
|
||||||
|
|
||||||
activity_data
|
|
||||||
|> Map.merge(act_data)
|
|
||||||
|> Map.put("object", Map.merge(object_data, obj_data))
|
|
||||||
|> Pleroma.Web.ActivityPub.ActivityPub.insert(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp user_mentions(users) do
|
|
||||||
user_mentions =
|
|
||||||
Enum.reduce(
|
|
||||||
@groups,
|
|
||||||
[],
|
|
||||||
fn group, acc ->
|
|
||||||
acc ++ get_random_mentions(users[group], Enum.random(0..2))
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
if Enum.random([true, false]),
|
|
||||||
do: ["@" <> users[:user].nickname | user_mentions],
|
|
||||||
else: user_mentions
|
|
||||||
end
|
|
||||||
|
|
||||||
defp hell_thread_mentions(users) do
|
|
||||||
with {:ok, nil} <- Cachex.get(:user_cache, "hell_thread_mentions") do
|
|
||||||
cached =
|
|
||||||
@groups
|
|
||||||
|> Enum.reduce([users[:user]], fn group, acc ->
|
|
||||||
acc ++ Enum.take(users[group], 5)
|
|
||||||
end)
|
|
||||||
|> Enum.map(&"@#{&1.nickname}")
|
|
||||||
|> Enum.join(", ")
|
|
||||||
|
|
||||||
Cachex.put(:user_cache, "hell_thread_mentions", cached)
|
|
||||||
cached
|
|
||||||
else
|
|
||||||
{:ok, cached} -> cached
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:simple, visibility, group, users, _opts)
|
|
||||||
when group in @remote_groups do
|
|
||||||
insert_remote_activity(visibility, group, users, "Remote status")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:simple, visibility, group, users, _opts) do
|
|
||||||
insert_local_activity(visibility, group, users, "Simple status")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:simple_filtered, visibility, group, users, _opts)
|
|
||||||
when group in @remote_groups do
|
|
||||||
insert_remote_activity(visibility, group, users, "Remote status which must be filtered")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:simple_filtered, visibility, group, users, _opts) do
|
|
||||||
insert_local_activity(visibility, group, users, "Simple status which must be filtered")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:emoji, visibility, group, users, _opts)
|
|
||||||
when group in @remote_groups do
|
|
||||||
insert_remote_activity(visibility, group, users, "Remote status with emoji :firefox:")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:emoji, visibility, group, users, _opts) do
|
|
||||||
insert_local_activity(visibility, group, users, "Simple status with emoji :firefox:")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:mentions, visibility, group, users, _opts)
|
|
||||||
when group in @remote_groups do
|
|
||||||
mentions = user_mentions(users)
|
|
||||||
|
|
||||||
status = Enum.join(mentions, ", ") <> " remote status with mentions"
|
|
||||||
|
|
||||||
insert_remote_activity(visibility, group, users, status)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:mentions, visibility, group, users, _opts) do
|
|
||||||
mentions = user_mentions(users)
|
|
||||||
|
|
||||||
status = Enum.join(mentions, ", ") <> " simple status with mentions"
|
|
||||||
insert_remote_activity(visibility, group, users, status)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:hell_thread, visibility, group, users, _)
|
|
||||||
when group in @remote_groups do
|
|
||||||
mentions = hell_thread_mentions(users)
|
|
||||||
insert_remote_activity(visibility, group, users, mentions <> " remote hell thread status")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:hell_thread, visibility, group, users, _opts) do
|
|
||||||
mentions = hell_thread_mentions(users)
|
|
||||||
|
|
||||||
insert_local_activity(visibility, group, users, mentions <> " hell thread status")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:attachment, visibility, group, users, _opts) do
|
|
||||||
actor = get_actor(group, users)
|
|
||||||
|
|
||||||
obj_data = %{
|
|
||||||
"actor" => actor.ap_id,
|
|
||||||
"name" => "4467-11.jpg",
|
|
||||||
"type" => "Document",
|
|
||||||
"url" => [
|
|
||||||
%{
|
|
||||||
"href" =>
|
|
||||||
"#{Pleroma.Web.Endpoint.url()}/media/b1b873552422a07bf53af01f3c231c841db4dfc42c35efde681abaf0f2a4eab7.jpg",
|
|
||||||
"mediaType" => "image/jpeg",
|
|
||||||
"type" => "Link"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
object = Repo.insert!(%Pleroma.Object{data: obj_data})
|
|
||||||
|
|
||||||
{:ok, _activity} =
|
|
||||||
CommonAPI.post(actor, %{
|
|
||||||
status: "Post with attachment",
|
|
||||||
visibility: visibility,
|
|
||||||
media_ids: [object.id]
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:tag, visibility, group, users, _opts) do
|
|
||||||
insert_local_activity(visibility, group, users, "Status with #tag")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:like, visibility, group, users, opts) do
|
|
||||||
actor = get_actor(group, users)
|
|
||||||
|
|
||||||
with activity_id when not is_nil(activity_id) <- get_random_create_activity_id(),
|
|
||||||
{:ok, _activity} <- CommonAPI.favorite(actor, activity_id) do
|
|
||||||
:ok
|
|
||||||
else
|
|
||||||
{:error, _} ->
|
|
||||||
insert_activity(:like, visibility, group, users, opts)
|
|
||||||
|
|
||||||
nil ->
|
|
||||||
Process.sleep(15)
|
|
||||||
insert_activity(:like, visibility, group, users, opts)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:reblog, visibility, group, users, opts) do
|
|
||||||
actor = get_actor(group, users)
|
|
||||||
|
|
||||||
with activity_id when not is_nil(activity_id) <- get_random_create_activity_id(),
|
|
||||||
{:ok, _activity} <- CommonAPI.repeat(activity_id, actor) do
|
|
||||||
:ok
|
|
||||||
else
|
|
||||||
{:error, _} ->
|
|
||||||
insert_activity(:reblog, visibility, group, users, opts)
|
|
||||||
|
|
||||||
nil ->
|
|
||||||
Process.sleep(15)
|
|
||||||
insert_activity(:reblog, visibility, group, users, opts)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:simple_thread, "direct", group, users, _opts) do
|
|
||||||
actor = get_actor(group, users)
|
|
||||||
tasks = get_reply_tasks("direct", group)
|
|
||||||
|
|
||||||
list =
|
|
||||||
case group do
|
|
||||||
:user ->
|
|
||||||
group = Enum.random(@friends_groups)
|
|
||||||
Enum.take(users[group], 3)
|
|
||||||
|
|
||||||
_ ->
|
|
||||||
Enum.take(users[group], 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
data = Enum.map(list, &("@" <> &1.nickname))
|
|
||||||
|
|
||||||
{:ok, activity} =
|
|
||||||
CommonAPI.post(actor, %{
|
|
||||||
status: Enum.join(data, ", ") <> "simple status",
|
|
||||||
visibility: "direct"
|
|
||||||
})
|
|
||||||
|
|
||||||
acc = {activity.id, ["@" <> users[:user].nickname | data] ++ ["reply to status"]}
|
|
||||||
insert_direct_replies(tasks, users[:user], list, acc)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_activity(:simple_thread, visibility, group, users, _opts) do
|
|
||||||
actor = get_actor(group, users)
|
|
||||||
tasks = get_reply_tasks(visibility, group)
|
|
||||||
|
|
||||||
{:ok, activity} =
|
|
||||||
CommonAPI.post(users[:user], %{status: "Simple status", visibility: visibility})
|
|
||||||
|
|
||||||
acc = {activity.id, ["@" <> actor.nickname, "reply to status"]}
|
|
||||||
insert_replies(tasks, visibility, users, acc)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_actor(:user, %{user: user}), do: user
|
|
||||||
defp get_actor(group, users), do: Enum.random(users[group])
|
|
||||||
|
|
||||||
defp other_data(actor, content) do
|
|
||||||
%{host: host} = URI.parse(actor.ap_id)
|
|
||||||
datetime = DateTime.utc_now() |> to_string()
|
|
||||||
context_id = "https://#{host}/contexts/#{UUID.generate()}"
|
|
||||||
activity_id = "https://#{host}/activities/#{UUID.generate()}"
|
|
||||||
object_id = "https://#{host}/objects/#{UUID.generate()}"
|
|
||||||
|
|
||||||
activity_data = %{
|
|
||||||
"actor" => actor.ap_id,
|
|
||||||
"context" => context_id,
|
|
||||||
"id" => activity_id,
|
|
||||||
"published" => datetime,
|
|
||||||
"type" => "Create",
|
|
||||||
"directMessage" => false
|
|
||||||
}
|
|
||||||
|
|
||||||
object_data = %{
|
|
||||||
"actor" => actor.ap_id,
|
|
||||||
"attachment" => [],
|
|
||||||
"attributedTo" => actor.ap_id,
|
|
||||||
"bcc" => [],
|
|
||||||
"bto" => [],
|
|
||||||
"content" => content,
|
|
||||||
"context" => context_id,
|
|
||||||
"conversation" => context_id,
|
|
||||||
"emoji" => %{},
|
|
||||||
"id" => object_id,
|
|
||||||
"published" => datetime,
|
|
||||||
"sensitive" => false,
|
|
||||||
"summary" => "",
|
|
||||||
"tag" => [],
|
|
||||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
|
||||||
"type" => "Note"
|
|
||||||
}
|
|
||||||
|
|
||||||
{activity_data, object_data}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp prepare_activity_data(actor, "public", _mention) do
|
|
||||||
obj_data = %{
|
|
||||||
"cc" => [actor.follower_address],
|
|
||||||
"to" => [Constants.as_public()]
|
|
||||||
}
|
|
||||||
|
|
||||||
act_data = %{
|
|
||||||
"cc" => [actor.follower_address],
|
|
||||||
"to" => [Constants.as_public()]
|
|
||||||
}
|
|
||||||
|
|
||||||
{act_data, obj_data}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp prepare_activity_data(actor, "private", _mention) do
|
|
||||||
obj_data = %{
|
|
||||||
"cc" => [],
|
|
||||||
"to" => [actor.follower_address]
|
|
||||||
}
|
|
||||||
|
|
||||||
act_data = %{
|
|
||||||
"cc" => [],
|
|
||||||
"to" => [actor.follower_address]
|
|
||||||
}
|
|
||||||
|
|
||||||
{act_data, obj_data}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp prepare_activity_data(actor, "unlisted", _mention) do
|
|
||||||
obj_data = %{
|
|
||||||
"cc" => [Constants.as_public()],
|
|
||||||
"to" => [actor.follower_address]
|
|
||||||
}
|
|
||||||
|
|
||||||
act_data = %{
|
|
||||||
"cc" => [Constants.as_public()],
|
|
||||||
"to" => [actor.follower_address]
|
|
||||||
}
|
|
||||||
|
|
||||||
{act_data, obj_data}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp prepare_activity_data(_actor, "direct", mention) do
|
|
||||||
%{host: mentioned_host} = URI.parse(mention.ap_id)
|
|
||||||
|
|
||||||
obj_data = %{
|
|
||||||
"cc" => [],
|
|
||||||
"content" =>
|
|
||||||
"<span class=\"h-card\"><a class=\"u-url mention\" href=\"#{mention.ap_id}\" rel=\"ugc\">@<span>#{
|
|
||||||
mention.nickname
|
|
||||||
}</span></a></span> direct message",
|
|
||||||
"tag" => [
|
|
||||||
%{
|
|
||||||
"href" => mention.ap_id,
|
|
||||||
"name" => "@#{mention.nickname}@#{mentioned_host}",
|
|
||||||
"type" => "Mention"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"to" => [mention.ap_id]
|
|
||||||
}
|
|
||||||
|
|
||||||
act_data = %{
|
|
||||||
"cc" => [],
|
|
||||||
"directMessage" => true,
|
|
||||||
"to" => [mention.ap_id]
|
|
||||||
}
|
|
||||||
|
|
||||||
{act_data, obj_data}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_reply_tasks("public", :user) do
|
|
||||||
[:friends_local, :friends_remote, :non_friends_local, :non_friends_remote, :user]
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_reply_tasks("public", group) when group in @friends_groups do
|
|
||||||
[:non_friends_local, :non_friends_remote, :user, :friends_local, :friends_remote]
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_reply_tasks("public", group) when group in @non_friends_groups do
|
|
||||||
[:user, :friends_local, :friends_remote, :non_friends_local, :non_friends_remote]
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_reply_tasks(visibility, :user) when visibility in ["unlisted", "private"] do
|
|
||||||
[:friends_local, :friends_remote, :user, :friends_local, :friends_remote]
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_reply_tasks(visibility, group)
|
|
||||||
when visibility in ["unlisted", "private"] and group in @friends_groups do
|
|
||||||
[:user, :friends_remote, :friends_local, :user]
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_reply_tasks(visibility, group)
|
|
||||||
when visibility in ["unlisted", "private"] and
|
|
||||||
group in @non_friends_groups,
|
|
||||||
do: []
|
|
||||||
|
|
||||||
defp get_reply_tasks("direct", :user), do: [:friends_local, :user, :friends_remote]
|
|
||||||
|
|
||||||
defp get_reply_tasks("direct", group) when group in @friends_groups,
|
|
||||||
do: [:user, group, :user]
|
|
||||||
|
|
||||||
defp get_reply_tasks("direct", group) when group in @non_friends_groups do
|
|
||||||
[:user, :non_friends_remote, :user, :non_friends_local]
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_replies(tasks, visibility, users, acc) do
|
|
||||||
Enum.reduce(tasks, acc, fn
|
|
||||||
:user, {id, data} ->
|
|
||||||
insert_reply(users[:user], data, id, visibility)
|
|
||||||
|
|
||||||
group, {id, data} ->
|
|
||||||
replier = Enum.random(users[group])
|
|
||||||
insert_reply(replier, data, id, visibility)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_direct_replies(tasks, user, list, acc) do
|
|
||||||
Enum.reduce(tasks, acc, fn
|
|
||||||
:user, {id, data} ->
|
|
||||||
{reply_id, _} = insert_reply(user, List.delete(data, "@" <> user.nickname), id, "direct")
|
|
||||||
{reply_id, data}
|
|
||||||
|
|
||||||
_, {id, data} ->
|
|
||||||
actor = Enum.random(list)
|
|
||||||
|
|
||||||
{reply_id, _} =
|
|
||||||
insert_reply(actor, List.delete(data, "@" <> actor.nickname), id, "direct")
|
|
||||||
|
|
||||||
{reply_id, data}
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp insert_reply(actor, data, activity_id, visibility) do
|
|
||||||
{:ok, reply} =
|
|
||||||
CommonAPI.post(actor, %{
|
|
||||||
status: Enum.join(data, ", "),
|
|
||||||
visibility: visibility,
|
|
||||||
in_reply_to_status_id: activity_id
|
|
||||||
})
|
|
||||||
|
|
||||||
{reply.id, ["@" <> actor.nickname | data]}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_random_mentions(_users, count) when count == 0, do: []
|
|
||||||
|
|
||||||
defp get_random_mentions(users, count) do
|
|
||||||
users
|
|
||||||
|> Enum.shuffle()
|
|
||||||
|> Enum.take(count)
|
|
||||||
|> Enum.map(&"@#{&1.nickname}")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_random_create_activity_id do
|
|
||||||
Repo.one(
|
|
||||||
from(a in Pleroma.Activity,
|
|
||||||
where: fragment("(?)->>'type' = ?", a.data, ^"Create"),
|
|
||||||
order_by: fragment("RANDOM()"),
|
|
||||||
limit: 1,
|
|
||||||
select: a.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,624 +0,0 @@
|
||||||
defmodule Pleroma.LoadTesting.Fetcher do
|
|
||||||
alias Pleroma.Activity
|
|
||||||
alias Pleroma.Pagination
|
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
|
||||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
|
||||||
|
|
||||||
@spec run_benchmarks(User.t()) :: any()
|
|
||||||
def run_benchmarks(user) do
|
|
||||||
fetch_user(user)
|
|
||||||
fetch_timelines(user)
|
|
||||||
render_views(user)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp formatters do
|
|
||||||
[
|
|
||||||
Benchee.Formatters.Console
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_user(user) do
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"By id" => fn -> Repo.get_by(User, id: user.id) end,
|
|
||||||
"By ap_id" => fn -> Repo.get_by(User, ap_id: user.ap_id) end,
|
|
||||||
"By email" => fn -> Repo.get_by(User, email: user.email) end,
|
|
||||||
"By nickname" => fn -> Repo.get_by(User, nickname: user.nickname) end
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp create_filter(user) do
|
|
||||||
Pleroma.Filter.create(%{
|
|
||||||
user_id: user.id,
|
|
||||||
phrase: "must be filtered",
|
|
||||||
hide: true,
|
|
||||||
context: ["home"]
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
defp delete_filter(filter), do: Repo.delete(filter)
|
|
||||||
|
|
||||||
defp fetch_timelines(user) do
|
|
||||||
fetch_home_timeline(user)
|
|
||||||
fetch_home_timeline_with_filter(user)
|
|
||||||
fetch_direct_timeline(user)
|
|
||||||
fetch_public_timeline(user)
|
|
||||||
fetch_public_timeline_with_filter(user)
|
|
||||||
fetch_public_timeline(user, :with_blocks)
|
|
||||||
fetch_public_timeline(user, :local)
|
|
||||||
fetch_public_timeline(user, :tag)
|
|
||||||
fetch_notifications(user)
|
|
||||||
fetch_favourites(user)
|
|
||||||
fetch_long_thread(user)
|
|
||||||
fetch_timelines_with_reply_filtering(user)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp render_views(user) do
|
|
||||||
render_timelines(user)
|
|
||||||
render_long_thread(user)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp opts_for_home_timeline(user) do
|
|
||||||
%{
|
|
||||||
blocking_user: user,
|
|
||||||
count: "20",
|
|
||||||
muting_user: user,
|
|
||||||
type: ["Create", "Announce"],
|
|
||||||
user: user,
|
|
||||||
with_muted: true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_home_timeline(user, title_end \\ "") do
|
|
||||||
opts = opts_for_home_timeline(user)
|
|
||||||
|
|
||||||
recipients = [user.ap_id | User.following(user)]
|
|
||||||
|
|
||||||
first_page_last =
|
|
||||||
ActivityPub.fetch_activities(recipients, opts) |> Enum.reverse() |> List.last()
|
|
||||||
|
|
||||||
second_page_last =
|
|
||||||
ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, first_page_last.id))
|
|
||||||
|> Enum.reverse()
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
third_page_last =
|
|
||||||
ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, second_page_last.id))
|
|
||||||
|> Enum.reverse()
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
forth_page_last =
|
|
||||||
ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, third_page_last.id))
|
|
||||||
|> Enum.reverse()
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
title = "home timeline " <> title_end
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
title => fn opts -> ActivityPub.fetch_activities(recipients, opts) end
|
|
||||||
},
|
|
||||||
inputs: %{
|
|
||||||
"1 page" => opts,
|
|
||||||
"2 page" => Map.put(opts, :max_id, first_page_last.id),
|
|
||||||
"3 page" => Map.put(opts, :max_id, second_page_last.id),
|
|
||||||
"4 page" => Map.put(opts, :max_id, third_page_last.id),
|
|
||||||
"5 page" => Map.put(opts, :max_id, forth_page_last.id),
|
|
||||||
"1 page only media" => Map.put(opts, :only_media, true),
|
|
||||||
"2 page only media" =>
|
|
||||||
Map.put(opts, :max_id, first_page_last.id) |> Map.put(:only_media, true),
|
|
||||||
"3 page only media" =>
|
|
||||||
Map.put(opts, :max_id, second_page_last.id) |> Map.put(:only_media, true),
|
|
||||||
"4 page only media" =>
|
|
||||||
Map.put(opts, :max_id, third_page_last.id) |> Map.put(:only_media, true),
|
|
||||||
"5 page only media" =>
|
|
||||||
Map.put(opts, :max_id, forth_page_last.id) |> Map.put(:only_media, true)
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_home_timeline_with_filter(user) do
|
|
||||||
{:ok, filter} = create_filter(user)
|
|
||||||
|
|
||||||
fetch_home_timeline(user, "with filters")
|
|
||||||
|
|
||||||
delete_filter(filter)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp opts_for_direct_timeline(user) do
|
|
||||||
%{
|
|
||||||
visibility: "direct",
|
|
||||||
blocking_user: user,
|
|
||||||
count: "20",
|
|
||||||
type: "Create",
|
|
||||||
user: user,
|
|
||||||
with_muted: true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_direct_timeline(user) do
|
|
||||||
recipients = [user.ap_id]
|
|
||||||
|
|
||||||
opts = opts_for_direct_timeline(user)
|
|
||||||
|
|
||||||
first_page_last =
|
|
||||||
recipients
|
|
||||||
|> ActivityPub.fetch_activities_query(opts)
|
|
||||||
|> Pagination.fetch_paginated(opts)
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
opts2 = Map.put(opts, :max_id, first_page_last.id)
|
|
||||||
|
|
||||||
second_page_last =
|
|
||||||
recipients
|
|
||||||
|> ActivityPub.fetch_activities_query(opts2)
|
|
||||||
|> Pagination.fetch_paginated(opts2)
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
opts3 = Map.put(opts, :max_id, second_page_last.id)
|
|
||||||
|
|
||||||
third_page_last =
|
|
||||||
recipients
|
|
||||||
|> ActivityPub.fetch_activities_query(opts3)
|
|
||||||
|> Pagination.fetch_paginated(opts3)
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
opts4 = Map.put(opts, :max_id, third_page_last.id)
|
|
||||||
|
|
||||||
forth_page_last =
|
|
||||||
recipients
|
|
||||||
|> ActivityPub.fetch_activities_query(opts4)
|
|
||||||
|> Pagination.fetch_paginated(opts4)
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"direct timeline" => fn opts ->
|
|
||||||
ActivityPub.fetch_activities_query(recipients, opts) |> Pagination.fetch_paginated(opts)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{
|
|
||||||
"1 page" => opts,
|
|
||||||
"2 page" => opts2,
|
|
||||||
"3 page" => opts3,
|
|
||||||
"4 page" => opts4,
|
|
||||||
"5 page" => Map.put(opts4, :max_id, forth_page_last.id)
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp opts_for_public_timeline(user) do
|
|
||||||
%{
|
|
||||||
type: ["Create", "Announce"],
|
|
||||||
local_only: false,
|
|
||||||
blocking_user: user,
|
|
||||||
muting_user: user
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp opts_for_public_timeline(user, :local) do
|
|
||||||
%{
|
|
||||||
type: ["Create", "Announce"],
|
|
||||||
local_only: true,
|
|
||||||
blocking_user: user,
|
|
||||||
muting_user: user
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp opts_for_public_timeline(user, :tag) do
|
|
||||||
%{
|
|
||||||
blocking_user: user,
|
|
||||||
count: "20",
|
|
||||||
local_only: nil,
|
|
||||||
muting_user: user,
|
|
||||||
tag: ["tag"],
|
|
||||||
tag_all: [],
|
|
||||||
tag_reject: [],
|
|
||||||
type: "Create",
|
|
||||||
user: user,
|
|
||||||
with_muted: true
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_public_timeline(user) do
|
|
||||||
opts = opts_for_public_timeline(user)
|
|
||||||
|
|
||||||
fetch_public_timeline(opts, "public timeline")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_public_timeline_with_filter(user) do
|
|
||||||
{:ok, filter} = create_filter(user)
|
|
||||||
opts = opts_for_public_timeline(user)
|
|
||||||
|
|
||||||
fetch_public_timeline(opts, "public timeline with filters")
|
|
||||||
delete_filter(filter)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_public_timeline(user, :local) do
|
|
||||||
opts = opts_for_public_timeline(user, :local)
|
|
||||||
|
|
||||||
fetch_public_timeline(opts, "public timeline only local")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_public_timeline(user, :tag) do
|
|
||||||
opts = opts_for_public_timeline(user, :tag)
|
|
||||||
|
|
||||||
fetch_public_timeline(opts, "hashtag timeline")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_public_timeline(user, :only_media) do
|
|
||||||
opts = opts_for_public_timeline(user) |> Map.put(:only_media, true)
|
|
||||||
|
|
||||||
fetch_public_timeline(opts, "public timeline only media")
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_public_timeline(user, :with_blocks) do
|
|
||||||
opts = opts_for_public_timeline(user)
|
|
||||||
|
|
||||||
remote_non_friends = Agent.get(:non_friends_remote, & &1)
|
|
||||||
|
|
||||||
Benchee.run(%{
|
|
||||||
"public timeline without blocks" => fn ->
|
|
||||||
ActivityPub.fetch_public_activities(opts)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
Enum.each(remote_non_friends, fn non_friend ->
|
|
||||||
{:ok, _} = User.block(user, non_friend)
|
|
||||||
end)
|
|
||||||
|
|
||||||
user = User.get_by_id(user.id)
|
|
||||||
|
|
||||||
opts = Map.put(opts, :blocking_user, user)
|
|
||||||
|
|
||||||
Benchee.run(%{
|
|
||||||
"public timeline with user block" => fn ->
|
|
||||||
ActivityPub.fetch_public_activities(opts)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
domains =
|
|
||||||
Enum.reduce(remote_non_friends, [], fn non_friend, domains ->
|
|
||||||
{:ok, _user} = User.unblock(user, non_friend)
|
|
||||||
%{host: host} = URI.parse(non_friend.ap_id)
|
|
||||||
[host | domains]
|
|
||||||
end)
|
|
||||||
|
|
||||||
domains = Enum.uniq(domains)
|
|
||||||
|
|
||||||
Enum.each(domains, fn domain ->
|
|
||||||
{:ok, _} = User.block_domain(user, domain)
|
|
||||||
end)
|
|
||||||
|
|
||||||
user = User.get_by_id(user.id)
|
|
||||||
opts = Map.put(opts, :blocking_user, user)
|
|
||||||
|
|
||||||
Benchee.run(%{
|
|
||||||
"public timeline with domain block" => fn ->
|
|
||||||
ActivityPub.fetch_public_activities(opts)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_public_timeline(opts, title) when is_binary(title) do
|
|
||||||
first_page_last = ActivityPub.fetch_public_activities(opts) |> List.last()
|
|
||||||
|
|
||||||
second_page_last =
|
|
||||||
ActivityPub.fetch_public_activities(Map.put(opts, :max_id, first_page_last.id))
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
third_page_last =
|
|
||||||
ActivityPub.fetch_public_activities(Map.put(opts, :max_id, second_page_last.id))
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
forth_page_last =
|
|
||||||
ActivityPub.fetch_public_activities(Map.put(opts, :max_id, third_page_last.id))
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
title => fn opts ->
|
|
||||||
ActivityPub.fetch_public_activities(opts)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{
|
|
||||||
"1 page" => opts,
|
|
||||||
"2 page" => Map.put(opts, :max_id, first_page_last.id),
|
|
||||||
"3 page" => Map.put(opts, :max_id, second_page_last.id),
|
|
||||||
"4 page" => Map.put(opts, :max_id, third_page_last.id),
|
|
||||||
"5 page" => Map.put(opts, :max_id, forth_page_last.id)
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp opts_for_notifications do
|
|
||||||
%{count: "20", with_muted: true}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_notifications(user) do
|
|
||||||
opts = opts_for_notifications()
|
|
||||||
|
|
||||||
first_page_last = MastodonAPI.get_notifications(user, opts) |> List.last()
|
|
||||||
|
|
||||||
second_page_last =
|
|
||||||
MastodonAPI.get_notifications(user, Map.put(opts, :max_id, first_page_last.id))
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
third_page_last =
|
|
||||||
MastodonAPI.get_notifications(user, Map.put(opts, :max_id, second_page_last.id))
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
forth_page_last =
|
|
||||||
MastodonAPI.get_notifications(user, Map.put(opts, :max_id, third_page_last.id))
|
|
||||||
|> List.last()
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"Notifications" => fn opts ->
|
|
||||||
MastodonAPI.get_notifications(user, opts)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{
|
|
||||||
"1 page" => opts,
|
|
||||||
"2 page" => Map.put(opts, :max_id, first_page_last.id),
|
|
||||||
"3 page" => Map.put(opts, :max_id, second_page_last.id),
|
|
||||||
"4 page" => Map.put(opts, :max_id, third_page_last.id),
|
|
||||||
"5 page" => Map.put(opts, :max_id, forth_page_last.id)
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_favourites(user) do
|
|
||||||
first_page_last = ActivityPub.fetch_favourites(user) |> List.last()
|
|
||||||
|
|
||||||
second_page_last =
|
|
||||||
ActivityPub.fetch_favourites(user, %{:max_id => first_page_last.id}) |> List.last()
|
|
||||||
|
|
||||||
third_page_last =
|
|
||||||
ActivityPub.fetch_favourites(user, %{:max_id => second_page_last.id}) |> List.last()
|
|
||||||
|
|
||||||
forth_page_last =
|
|
||||||
ActivityPub.fetch_favourites(user, %{:max_id => third_page_last.id}) |> List.last()
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"Favourites" => fn opts ->
|
|
||||||
ActivityPub.fetch_favourites(user, opts)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{
|
|
||||||
"1 page" => %{},
|
|
||||||
"2 page" => %{:max_id => first_page_last.id},
|
|
||||||
"3 page" => %{:max_id => second_page_last.id},
|
|
||||||
"4 page" => %{:max_id => third_page_last.id},
|
|
||||||
"5 page" => %{:max_id => forth_page_last.id}
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp opts_for_long_thread(user) do
|
|
||||||
%{
|
|
||||||
blocking_user: user,
|
|
||||||
user: user
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_long_thread(user) do
|
|
||||||
%{public_thread: public, private_thread: private} =
|
|
||||||
Agent.get(:benchmark_state, fn state -> state end)
|
|
||||||
|
|
||||||
opts = opts_for_long_thread(user)
|
|
||||||
|
|
||||||
private_input = {private.data["context"], Map.put(opts, :exclude_id, private.id)}
|
|
||||||
|
|
||||||
public_input = {public.data["context"], Map.put(opts, :exclude_id, public.id)}
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"fetch context" => fn {context, opts} ->
|
|
||||||
ActivityPub.fetch_activities_for_context(context, opts)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{
|
|
||||||
"Private long thread" => private_input,
|
|
||||||
"Public long thread" => public_input
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp render_timelines(user) do
|
|
||||||
opts = opts_for_home_timeline(user)
|
|
||||||
|
|
||||||
recipients = [user.ap_id | User.following(user)]
|
|
||||||
|
|
||||||
home_activities = ActivityPub.fetch_activities(recipients, opts) |> Enum.reverse()
|
|
||||||
|
|
||||||
recipients = [user.ap_id]
|
|
||||||
|
|
||||||
opts = opts_for_direct_timeline(user)
|
|
||||||
|
|
||||||
direct_activities =
|
|
||||||
recipients
|
|
||||||
|> ActivityPub.fetch_activities_query(opts)
|
|
||||||
|> Pagination.fetch_paginated(opts)
|
|
||||||
|
|
||||||
opts = opts_for_public_timeline(user)
|
|
||||||
|
|
||||||
public_activities = ActivityPub.fetch_public_activities(opts)
|
|
||||||
|
|
||||||
opts = opts_for_public_timeline(user, :tag)
|
|
||||||
|
|
||||||
tag_activities = ActivityPub.fetch_public_activities(opts)
|
|
||||||
|
|
||||||
opts = opts_for_notifications()
|
|
||||||
|
|
||||||
notifications = MastodonAPI.get_notifications(user, opts)
|
|
||||||
|
|
||||||
favourites = ActivityPub.fetch_favourites(user)
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"Rendering home timeline" => fn ->
|
|
||||||
StatusView.render("index.json", %{
|
|
||||||
activities: home_activities,
|
|
||||||
for: user,
|
|
||||||
as: :activity
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
"Rendering direct timeline" => fn ->
|
|
||||||
StatusView.render("index.json", %{
|
|
||||||
activities: direct_activities,
|
|
||||||
for: user,
|
|
||||||
as: :activity
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
"Rendering public timeline" => fn ->
|
|
||||||
StatusView.render("index.json", %{
|
|
||||||
activities: public_activities,
|
|
||||||
for: user,
|
|
||||||
as: :activity
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
"Rendering tag timeline" => fn ->
|
|
||||||
StatusView.render("index.json", %{
|
|
||||||
activities: tag_activities,
|
|
||||||
for: user,
|
|
||||||
as: :activity
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
"Rendering notifications" => fn ->
|
|
||||||
Pleroma.Web.MastodonAPI.NotificationView.render("index.json", %{
|
|
||||||
notifications: notifications,
|
|
||||||
for: user
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
"Rendering favourites timeline" => fn ->
|
|
||||||
StatusView.render("index.json", %{
|
|
||||||
activities: favourites,
|
|
||||||
for: user,
|
|
||||||
as: :activity
|
|
||||||
})
|
|
||||||
end
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp render_long_thread(user) do
|
|
||||||
%{public_thread: public, private_thread: private} =
|
|
||||||
Agent.get(:benchmark_state, fn state -> state end)
|
|
||||||
|
|
||||||
opts = %{for: user}
|
|
||||||
public_activity = Activity.get_by_id_with_object(public.id)
|
|
||||||
private_activity = Activity.get_by_id_with_object(private.id)
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"render" => fn opts ->
|
|
||||||
StatusView.render("show.json", opts)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{
|
|
||||||
"Public root" => Map.put(opts, :activity, public_activity),
|
|
||||||
"Private root" => Map.put(opts, :activity, private_activity)
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
|
|
||||||
fetch_opts = opts_for_long_thread(user)
|
|
||||||
|
|
||||||
public_context =
|
|
||||||
ActivityPub.fetch_activities_for_context(
|
|
||||||
public.data["context"],
|
|
||||||
Map.put(fetch_opts, :exclude_id, public.id)
|
|
||||||
)
|
|
||||||
|
|
||||||
private_context =
|
|
||||||
ActivityPub.fetch_activities_for_context(
|
|
||||||
private.data["context"],
|
|
||||||
Map.put(fetch_opts, :exclude_id, private.id)
|
|
||||||
)
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"render" => fn opts ->
|
|
||||||
StatusView.render("context.json", opts)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{
|
|
||||||
"Public context" => %{user: user, activity: public_activity, activities: public_context},
|
|
||||||
"Private context" => %{
|
|
||||||
user: user,
|
|
||||||
activity: private_activity,
|
|
||||||
activities: private_context
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_timelines_with_reply_filtering(user) do
|
|
||||||
public_params = opts_for_public_timeline(user)
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"Public timeline without reply filtering" => fn ->
|
|
||||||
ActivityPub.fetch_public_activities(public_params)
|
|
||||||
end,
|
|
||||||
"Public timeline with reply filtering - following" => fn ->
|
|
||||||
public_params
|
|
||||||
|> Map.put(:reply_visibility, "following")
|
|
||||||
|> Map.put(:reply_filtering_user, user)
|
|
||||||
|> ActivityPub.fetch_public_activities()
|
|
||||||
end,
|
|
||||||
"Public timeline with reply filtering - self" => fn ->
|
|
||||||
public_params
|
|
||||||
|> Map.put(:reply_visibility, "self")
|
|
||||||
|> Map.put(:reply_filtering_user, user)
|
|
||||||
|> ActivityPub.fetch_public_activities()
|
|
||||||
end
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
|
|
||||||
private_params = opts_for_home_timeline(user)
|
|
||||||
|
|
||||||
recipients = [user.ap_id | User.following(user)]
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"Home timeline without reply filtering" => fn ->
|
|
||||||
ActivityPub.fetch_activities(recipients, private_params)
|
|
||||||
end,
|
|
||||||
"Home timeline with reply filtering - following" => fn ->
|
|
||||||
private_params =
|
|
||||||
private_params
|
|
||||||
|> Map.put(:reply_filtering_user, user)
|
|
||||||
|> Map.put(:reply_visibility, "following")
|
|
||||||
|
|
||||||
ActivityPub.fetch_activities(recipients, private_params)
|
|
||||||
end,
|
|
||||||
"Home timeline with reply filtering - self" => fn ->
|
|
||||||
private_params =
|
|
||||||
private_params
|
|
||||||
|> Map.put(:reply_filtering_user, user)
|
|
||||||
|> Map.put(:reply_visibility, "self")
|
|
||||||
|
|
||||||
ActivityPub.fetch_activities(recipients, private_params)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
formatters: formatters()
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,14 +0,0 @@
|
||||||
defmodule Pleroma.LoadTesting.Helper do
|
|
||||||
alias Ecto.Adapters.SQL
|
|
||||||
alias Pleroma.Repo
|
|
||||||
|
|
||||||
def to_sec(microseconds), do: microseconds / 1_000_000
|
|
||||||
|
|
||||||
def clean_tables do
|
|
||||||
IO.puts("Deleting old data...\n")
|
|
||||||
SQL.query!(Repo, "TRUNCATE users CASCADE;")
|
|
||||||
SQL.query!(Repo, "TRUNCATE activities CASCADE;")
|
|
||||||
SQL.query!(Repo, "TRUNCATE objects CASCADE;")
|
|
||||||
SQL.query!(Repo, "TRUNCATE oban_jobs CASCADE;")
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,189 +0,0 @@
|
||||||
defmodule Pleroma.LoadTesting.Users do
|
|
||||||
@moduledoc """
|
|
||||||
Module for generating users with friends.
|
|
||||||
"""
|
|
||||||
import Ecto.Query
|
|
||||||
import Pleroma.LoadTesting.Helper, only: [to_sec: 1]
|
|
||||||
|
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.User.Query
|
|
||||||
|
|
||||||
@defaults [
|
|
||||||
users: 20_000,
|
|
||||||
friends: 100
|
|
||||||
]
|
|
||||||
|
|
||||||
@max_concurrency 10
|
|
||||||
|
|
||||||
@spec generate(keyword()) :: User.t()
|
|
||||||
def generate(opts \\ []) do
|
|
||||||
opts = Keyword.merge(@defaults, opts)
|
|
||||||
|
|
||||||
generate_users(opts[:users])
|
|
||||||
|
|
||||||
main_user =
|
|
||||||
Repo.one(from(u in User, where: u.local == true, order_by: fragment("RANDOM()"), limit: 1))
|
|
||||||
|
|
||||||
make_friends(main_user, opts[:friends])
|
|
||||||
|
|
||||||
User.get_by_id(main_user.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def generate_users(max) do
|
|
||||||
IO.puts("Starting generating #{max} users...")
|
|
||||||
|
|
||||||
{time, users} =
|
|
||||||
:timer.tc(fn ->
|
|
||||||
Task.async_stream(
|
|
||||||
1..max,
|
|
||||||
&generate_user(&1),
|
|
||||||
max_concurrency: @max_concurrency,
|
|
||||||
timeout: 30_000
|
|
||||||
)
|
|
||||||
|> Enum.to_list()
|
|
||||||
end)
|
|
||||||
|
|
||||||
IO.puts("Generating users took #{to_sec(time)} sec.\n")
|
|
||||||
users
|
|
||||||
end
|
|
||||||
|
|
||||||
defp generate_user(i) do
|
|
||||||
remote = Enum.random([true, false])
|
|
||||||
|
|
||||||
%User{
|
|
||||||
name: "Test テスト User #{i}",
|
|
||||||
email: "user#{i}@example.com",
|
|
||||||
nickname: "nick#{i}",
|
|
||||||
password_hash: Pleroma.Password.Pbkdf2.hash_pwd_salt("test"),
|
|
||||||
bio: "Tester Number #{i}",
|
|
||||||
local: !remote
|
|
||||||
}
|
|
||||||
|> user_urls()
|
|
||||||
|> Repo.insert!()
|
|
||||||
end
|
|
||||||
|
|
||||||
defp user_urls(%{local: true} = user) do
|
|
||||||
urls = %{
|
|
||||||
ap_id: User.ap_id(user),
|
|
||||||
follower_address: User.ap_followers(user),
|
|
||||||
following_address: User.ap_following(user)
|
|
||||||
}
|
|
||||||
|
|
||||||
Map.merge(user, urls)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp user_urls(%{local: false} = user) do
|
|
||||||
base_domain = Enum.random(["domain1.com", "domain2.com", "domain3.com"])
|
|
||||||
|
|
||||||
ap_id = "https://#{base_domain}/users/#{user.nickname}"
|
|
||||||
|
|
||||||
urls = %{
|
|
||||||
ap_id: ap_id,
|
|
||||||
follower_address: ap_id <> "/followers",
|
|
||||||
following_address: ap_id <> "/following"
|
|
||||||
}
|
|
||||||
|
|
||||||
Map.merge(user, urls)
|
|
||||||
end
|
|
||||||
|
|
||||||
def make_friends(main_user, max) when is_integer(max) do
|
|
||||||
IO.puts("Starting making friends for #{max} users...")
|
|
||||||
|
|
||||||
{time, _} =
|
|
||||||
:timer.tc(fn ->
|
|
||||||
number_of_users =
|
|
||||||
(max / 2)
|
|
||||||
|> Kernel.trunc()
|
|
||||||
|
|
||||||
main_user
|
|
||||||
|> get_users(%{limit: number_of_users, local: :local})
|
|
||||||
|> run_stream(main_user)
|
|
||||||
|
|
||||||
main_user
|
|
||||||
|> get_users(%{limit: number_of_users, local: :external})
|
|
||||||
|> run_stream(main_user)
|
|
||||||
end)
|
|
||||||
|
|
||||||
IO.puts("Making friends took #{to_sec(time)} sec.\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
def make_friends(%User{} = main_user, %User{} = user) do
|
|
||||||
{:ok, _, _} = User.follow(main_user, user)
|
|
||||||
{:ok, _, _} = User.follow(user, main_user)
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec get_users(User.t(), keyword()) :: [User.t()]
|
|
||||||
def get_users(user, opts) do
|
|
||||||
criteria = %{limit: opts[:limit]}
|
|
||||||
|
|
||||||
criteria =
|
|
||||||
if opts[:local] do
|
|
||||||
Map.put(criteria, opts[:local], true)
|
|
||||||
else
|
|
||||||
criteria
|
|
||||||
end
|
|
||||||
|
|
||||||
criteria =
|
|
||||||
if opts[:friends?] do
|
|
||||||
Map.put(criteria, :friends, user)
|
|
||||||
else
|
|
||||||
criteria
|
|
||||||
end
|
|
||||||
|
|
||||||
query =
|
|
||||||
criteria
|
|
||||||
|> Query.build()
|
|
||||||
|> random_without_user(user)
|
|
||||||
|
|
||||||
query =
|
|
||||||
if opts[:friends?] == false do
|
|
||||||
friends_ids =
|
|
||||||
%{friends: user}
|
|
||||||
|> Query.build()
|
|
||||||
|> Repo.all()
|
|
||||||
|> Enum.map(& &1.id)
|
|
||||||
|
|
||||||
from(u in query, where: u.id not in ^friends_ids)
|
|
||||||
else
|
|
||||||
query
|
|
||||||
end
|
|
||||||
|
|
||||||
Repo.all(query)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp random_without_user(query, user) do
|
|
||||||
from(u in query,
|
|
||||||
where: u.id != ^user.id,
|
|
||||||
order_by: fragment("RANDOM()")
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp run_stream(users, main_user) do
|
|
||||||
Task.async_stream(users, &make_friends(main_user, &1),
|
|
||||||
max_concurrency: @max_concurrency,
|
|
||||||
timeout: 30_000
|
|
||||||
)
|
|
||||||
|> Stream.run()
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec prepare_users(User.t(), keyword()) :: map()
|
|
||||||
def prepare_users(user, opts) do
|
|
||||||
friends_limit = opts[:friends_used]
|
|
||||||
non_friends_limit = opts[:non_friends_used]
|
|
||||||
|
|
||||||
%{
|
|
||||||
user: user,
|
|
||||||
friends_local: fetch_users(user, friends_limit, :local, true),
|
|
||||||
friends_remote: fetch_users(user, friends_limit, :external, true),
|
|
||||||
non_friends_local: fetch_users(user, non_friends_limit, :local, false),
|
|
||||||
non_friends_remote: fetch_users(user, non_friends_limit, :external, false)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp fetch_users(user, limit, local, friends?) do
|
|
||||||
user
|
|
||||||
|> get_users(limit: limit, local: local, friends?: friends?)
|
|
||||||
|> Enum.shuffle()
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,114 +0,0 @@
|
||||||
defmodule Mix.Tasks.Pleroma.Benchmarks.Tags do
|
|
||||||
use Mix.Task
|
|
||||||
|
|
||||||
import Pleroma.LoadTesting.Helper, only: [clean_tables: 0]
|
|
||||||
import Ecto.Query
|
|
||||||
|
|
||||||
alias Pleroma.Repo
|
|
||||||
|
|
||||||
def run(_args) do
|
|
||||||
Mix.Pleroma.start_pleroma()
|
|
||||||
activities_count = Repo.aggregate(from(a in Pleroma.Activity), :count, :id)
|
|
||||||
|
|
||||||
if activities_count == 0 do
|
|
||||||
IO.puts("Did not find any activities, cleaning and generating")
|
|
||||||
clean_tables()
|
|
||||||
Pleroma.LoadTesting.Users.generate_users(10)
|
|
||||||
Pleroma.LoadTesting.Activities.generate_tagged_activities()
|
|
||||||
else
|
|
||||||
IO.puts("Found #{activities_count} activities, won't generate new ones")
|
|
||||||
end
|
|
||||||
|
|
||||||
tags = Enum.map(0..20, fn i -> {"For #tag_#{i}", "tag_#{i}"} end)
|
|
||||||
|
|
||||||
Enum.each(tags, fn {_, tag} ->
|
|
||||||
query =
|
|
||||||
from(o in Pleroma.Object,
|
|
||||||
where: fragment("(?)->'tag' \\? (?)", o.data, ^tag)
|
|
||||||
)
|
|
||||||
|
|
||||||
count = Repo.aggregate(query, :count, :id)
|
|
||||||
IO.puts("Database contains #{count} posts tagged with #{tag}")
|
|
||||||
end)
|
|
||||||
|
|
||||||
user = Repo.all(Pleroma.User) |> List.first()
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"Hashtag fetching, any" => fn tags ->
|
|
||||||
hashtag_fetching(
|
|
||||||
%{
|
|
||||||
"any" => tags
|
|
||||||
},
|
|
||||||
user,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
end,
|
|
||||||
# Will always return zero results because no overlapping hashtags are generated.
|
|
||||||
"Hashtag fetching, all" => fn tags ->
|
|
||||||
hashtag_fetching(
|
|
||||||
%{
|
|
||||||
"all" => tags
|
|
||||||
},
|
|
||||||
user,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs:
|
|
||||||
tags
|
|
||||||
|> Enum.map(fn {_, v} -> v end)
|
|
||||||
|> Enum.chunk_every(2)
|
|
||||||
|> Enum.map(fn tags -> {"For #{inspect(tags)}", tags} end),
|
|
||||||
time: 5
|
|
||||||
)
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"Hashtag fetching" => fn tag ->
|
|
||||||
hashtag_fetching(
|
|
||||||
%{
|
|
||||||
"tag" => tag
|
|
||||||
},
|
|
||||||
user,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: tags,
|
|
||||||
time: 5
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp hashtag_fetching(params, user, local_only) do
|
|
||||||
tags =
|
|
||||||
[params["tag"], params["any"]]
|
|
||||||
|> List.flatten()
|
|
||||||
|> Enum.uniq()
|
|
||||||
|> Enum.filter(& &1)
|
|
||||||
|> Enum.map(&String.downcase(&1))
|
|
||||||
|
|
||||||
tag_all =
|
|
||||||
params
|
|
||||||
|> Map.get("all", [])
|
|
||||||
|> Enum.map(&String.downcase(&1))
|
|
||||||
|
|
||||||
tag_reject =
|
|
||||||
params
|
|
||||||
|> Map.get("none", [])
|
|
||||||
|> Enum.map(&String.downcase(&1))
|
|
||||||
|
|
||||||
_activities =
|
|
||||||
%{
|
|
||||||
type: "Create",
|
|
||||||
local_only: local_only,
|
|
||||||
blocking_user: user,
|
|
||||||
muting_user: user,
|
|
||||||
user: user,
|
|
||||||
tag: tags,
|
|
||||||
tag_all: tag_all,
|
|
||||||
tag_reject: tag_reject,
|
|
||||||
}
|
|
||||||
|> Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities()
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,70 +0,0 @@
|
||||||
defmodule Mix.Tasks.Pleroma.Benchmarks.Timelines do
|
|
||||||
use Mix.Task
|
|
||||||
|
|
||||||
import Pleroma.LoadTesting.Helper, only: [clean_tables: 0]
|
|
||||||
|
|
||||||
alias Pleroma.Web.CommonAPI
|
|
||||||
alias Plug.Conn
|
|
||||||
|
|
||||||
def run(_args) do
|
|
||||||
Mix.Pleroma.start_pleroma()
|
|
||||||
|
|
||||||
# Cleaning tables
|
|
||||||
clean_tables()
|
|
||||||
|
|
||||||
[{:ok, user} | users] = Pleroma.LoadTesting.Users.generate_users(1000)
|
|
||||||
|
|
||||||
# Let the user make 100 posts
|
|
||||||
|
|
||||||
1..100
|
|
||||||
|> Enum.each(fn i -> CommonAPI.post(user, %{status: to_string(i)}) end)
|
|
||||||
|
|
||||||
# Let 10 random users post
|
|
||||||
posts =
|
|
||||||
users
|
|
||||||
|> Enum.take_random(10)
|
|
||||||
|> Enum.map(fn {:ok, random_user} ->
|
|
||||||
{:ok, activity} = CommonAPI.post(random_user, %{status: "."})
|
|
||||||
activity
|
|
||||||
end)
|
|
||||||
|
|
||||||
# let our user repeat them
|
|
||||||
posts
|
|
||||||
|> Enum.each(fn activity ->
|
|
||||||
CommonAPI.repeat(activity.id, user)
|
|
||||||
end)
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"user timeline, no followers" => fn reading_user ->
|
|
||||||
conn =
|
|
||||||
Phoenix.ConnTest.build_conn()
|
|
||||||
|> Conn.assign(:user, reading_user)
|
|
||||||
|> Conn.assign(:skip_link_headers, true)
|
|
||||||
|
|
||||||
Pleroma.Web.MastodonAPI.AccountController.statuses(conn, %{id: user.id})
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{"user" => user, "no user" => nil},
|
|
||||||
time: 60
|
|
||||||
)
|
|
||||||
|
|
||||||
users
|
|
||||||
|> Enum.each(fn {:ok, follower} -> Pleroma.User.follow(follower, user) end)
|
|
||||||
|
|
||||||
Benchee.run(
|
|
||||||
%{
|
|
||||||
"user timeline, all following" => fn reading_user ->
|
|
||||||
conn =
|
|
||||||
Phoenix.ConnTest.build_conn()
|
|
||||||
|> Conn.assign(:user, reading_user)
|
|
||||||
|> Conn.assign(:skip_link_headers, true)
|
|
||||||
|
|
||||||
Pleroma.Web.MastodonAPI.AccountController.statuses(conn, %{id: user.id})
|
|
||||||
end
|
|
||||||
},
|
|
||||||
inputs: %{"user" => user, "no user" => nil},
|
|
||||||
time: 60
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,67 +0,0 @@
|
||||||
defmodule Mix.Tasks.Pleroma.LoadTesting do
|
|
||||||
use Mix.Task
|
|
||||||
import Ecto.Query
|
|
||||||
import Pleroma.LoadTesting.Helper, only: [clean_tables: 0]
|
|
||||||
|
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.User
|
|
||||||
|
|
||||||
@shortdoc "Factory for generation data"
|
|
||||||
@moduledoc """
|
|
||||||
Generates data like:
|
|
||||||
- local/remote users
|
|
||||||
- local/remote activities with differrent visibility:
|
|
||||||
- simple activiities
|
|
||||||
- with emoji
|
|
||||||
- with mentions
|
|
||||||
- hellthreads
|
|
||||||
- with attachments
|
|
||||||
- with tags
|
|
||||||
- likes
|
|
||||||
- reblogs
|
|
||||||
- simple threads
|
|
||||||
- long threads
|
|
||||||
|
|
||||||
## Generate data
|
|
||||||
MIX_ENV=benchmark mix pleroma.load_testing --users 20000 --friends 1000 --iterations 170 --friends_used 20 --non_friends_used 20
|
|
||||||
MIX_ENV=benchmark mix pleroma.load_testing -u 20000 -f 1000 -i 170 -fu 20 -nfu 20
|
|
||||||
|
|
||||||
Options:
|
|
||||||
- `--users NUMBER` - number of users to generate. Defaults to: 20000. Alias: `-u`
|
|
||||||
- `--friends NUMBER` - number of friends for main user. Defaults to: 1000. Alias: `-f`
|
|
||||||
- `--iterations NUMBER` - number of iterations to generate activities. For each iteration in database is inserted about 120+ activities with different visibility, actors and types.Defaults to: 170. Alias: `-i`
|
|
||||||
- `--friends_used NUMBER` - number of main user friends used in activity generation. Defaults to: 20. Alias: `-fu`
|
|
||||||
- `--non_friends_used NUMBER` - number of non friends used in activity generation. Defaults to: 20. Alias: `-nfu`
|
|
||||||
"""
|
|
||||||
|
|
||||||
@aliases [u: :users, f: :friends, i: :iterations, fu: :friends_used, nfu: :non_friends_used]
|
|
||||||
@switches [
|
|
||||||
users: :integer,
|
|
||||||
friends: :integer,
|
|
||||||
iterations: :integer,
|
|
||||||
friends_used: :integer,
|
|
||||||
non_friends_used: :integer
|
|
||||||
]
|
|
||||||
|
|
||||||
def run(args) do
|
|
||||||
Logger.configure(level: :error)
|
|
||||||
Mix.Pleroma.start_pleroma()
|
|
||||||
clean_tables()
|
|
||||||
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
|
|
||||||
|
|
||||||
user = Pleroma.LoadTesting.Users.generate(opts)
|
|
||||||
Pleroma.LoadTesting.Activities.generate(user, opts)
|
|
||||||
|
|
||||||
IO.puts("Users in DB: #{Repo.aggregate(from(u in User), :count, :id)}")
|
|
||||||
|
|
||||||
IO.puts("Activities in DB: #{Repo.aggregate(from(a in Pleroma.Activity), :count, :id)}")
|
|
||||||
|
|
||||||
IO.puts("Objects in DB: #{Repo.aggregate(from(o in Pleroma.Object), :count, :id)}")
|
|
||||||
|
|
||||||
IO.puts(
|
|
||||||
"Notifications in DB: #{Repo.aggregate(from(n in Pleroma.Notification), :count, :id)}"
|
|
||||||
)
|
|
||||||
|
|
||||||
Pleroma.LoadTesting.Fetcher.run_benchmarks(user)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
FROM elixir:1.11.4
|
|
||||||
|
|
||||||
# Single RUN statement, otherwise intermediate images are created
|
|
||||||
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
|
|
||||||
RUN apt-get update &&\
|
|
||||||
apt-get install -y libmagic-dev cmake libimage-exiftool-perl ffmpeg &&\
|
|
||||||
mix local.hex --force &&\
|
|
||||||
mix local.rebar --force
|
|
12
ci/README
12
ci/README
|
@ -1,12 +0,0 @@
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
Assuming an AMD64 Alpine system, you're going to need the following packages
|
|
||||||
- `qemu qemu-openrc qemu-arm qemu-aarch64` for binfmt
|
|
||||||
- `docker-cli-buildx` for building the images
|
|
||||||
|
|
||||||
## Setting up
|
|
||||||
|
|
||||||
```
|
|
||||||
docker login git.pleroma.social:5050
|
|
||||||
doas rc-service qemu-binfmt start
|
|
||||||
```
|
|
|
@ -1 +0,0 @@
|
||||||
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:latest --push .
|
|
|
@ -1,88 +0,0 @@
|
||||||
import Config
|
|
||||||
|
|
||||||
# We don't run a server during test. If one is required,
|
|
||||||
# you can enable the server option below.
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
|
||||||
http: [port: 4001],
|
|
||||||
url: [port: 4001]
|
|
||||||
|
|
||||||
# Disable captha for tests
|
|
||||||
config :pleroma, Pleroma.Captcha,
|
|
||||||
# It should not be enabled for automatic tests
|
|
||||||
enabled: false,
|
|
||||||
# A fake captcha service for tests
|
|
||||||
method: Pleroma.Captcha.Mock
|
|
||||||
|
|
||||||
# Print only warnings and errors during test
|
|
||||||
config :logger, level: :warn
|
|
||||||
|
|
||||||
config :pleroma, :auth, oauth_consumer_strategies: []
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Upload, filters: [], link_name: false
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Test, enabled: true
|
|
||||||
|
|
||||||
config :pleroma, :instance,
|
|
||||||
email: "admin@example.com",
|
|
||||||
notify_email: "noreply@example.com",
|
|
||||||
skip_thread_containment: false,
|
|
||||||
federating: false,
|
|
||||||
external_user_synchronization: false
|
|
||||||
|
|
||||||
config :pleroma, :activitypub, sign_object_fetches: false
|
|
||||||
|
|
||||||
# Configure your database
|
|
||||||
config :pleroma, Pleroma.Repo,
|
|
||||||
adapter: Ecto.Adapters.Postgres,
|
|
||||||
username: "postgres",
|
|
||||||
password: "postgres",
|
|
||||||
database: "pleroma_benchmark",
|
|
||||||
hostname: System.get_env("DB_HOST") || "localhost",
|
|
||||||
port: System.get_env("DB_PORT") || "5432",
|
|
||||||
pool_size: 10
|
|
||||||
|
|
||||||
# Reduce hash rounds for testing
|
|
||||||
config :pleroma, :password, iterations: 1
|
|
||||||
|
|
||||||
config :tesla, adapter: Tesla.Mock
|
|
||||||
|
|
||||||
config :pleroma, :rich_media,
|
|
||||||
enabled: false,
|
|
||||||
ignore_hosts: [],
|
|
||||||
ignore_tld: ["local", "localdomain", "lan"]
|
|
||||||
|
|
||||||
config :web_push_encryption, :vapid_details,
|
|
||||||
subject: "mailto:administrator@example.com",
|
|
||||||
public_key:
|
|
||||||
"BLH1qVhJItRGCfxgTtONfsOKDc9VRAraXw-3NsmjMngWSh7NxOizN6bkuRA7iLTMPS82PjwJAr3UoK9EC1IFrz4",
|
|
||||||
private_key: "_-XZ0iebPrRfZ_o0-IatTdszYa8VCH1yLN-JauK7HHA"
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.ScheduledActivity,
|
|
||||||
daily_user_limit: 2,
|
|
||||||
total_user_limit: 3,
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
config :pleroma, :rate_limit,
|
|
||||||
search: [{1000, 30}, {1000, 30}],
|
|
||||||
app_account_creation: {10_000, 5},
|
|
||||||
password_reset: {1000, 30}
|
|
||||||
|
|
||||||
config :pleroma, :http_security, report_uri: "https://endpoint.com"
|
|
||||||
|
|
||||||
config :pleroma, :http, send_user_agent: false
|
|
||||||
|
|
||||||
rum_enabled = System.get_env("RUM_ENABLED") == "true"
|
|
||||||
config :pleroma, :database, rum_enabled: rum_enabled
|
|
||||||
IO.puts("RUM enabled: #{rum_enabled}")
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
|
|
||||||
|
|
||||||
if File.exists?("./config/benchmark.secret.exs") do
|
|
||||||
import_config "benchmark.secret.exs"
|
|
||||||
else
|
|
||||||
IO.puts(
|
|
||||||
"You may want to create benchmark.secret.exs to declare custom database connection parameters."
|
|
||||||
)
|
|
||||||
end
|
|
|
@ -37,23 +37,38 @@
|
||||||
# FIGURATION! EDIT YOUR SECRET FILE (either prod.secret.exs, dev.secret.exs).
|
# FIGURATION! EDIT YOUR SECRET FILE (either prod.secret.exs, dev.secret.exs).
|
||||||
#
|
#
|
||||||
# This file is responsible for configuring your application
|
# This file is responsible for configuring your application
|
||||||
# and its dependencies with the aid of the Config module.
|
# and its dependencies with the aid of the Mix.Config module.
|
||||||
#
|
#
|
||||||
# This configuration file is loaded before any dependency and
|
# This configuration file is loaded before any dependency and
|
||||||
# is restricted to this project.
|
# is restricted to this project.
|
||||||
import Config
|
use Mix.Config
|
||||||
|
|
||||||
# General application configuration
|
# General application configuration
|
||||||
config :pleroma, ecto_repos: [Pleroma.Repo]
|
config :pleroma, ecto_repos: [Pleroma.Repo]
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
|
types: Pleroma.PostgresTypes,
|
||||||
telemetry_event: [Pleroma.Repo.Instrumenter],
|
telemetry_event: [Pleroma.Repo.Instrumenter],
|
||||||
migration_lock: nil
|
migration_lock: nil
|
||||||
|
|
||||||
config :pleroma, Pleroma.Captcha,
|
config :pleroma, Pleroma.Captcha,
|
||||||
enabled: true,
|
enabled: false,
|
||||||
seconds_valid: 300,
|
seconds_valid: 60,
|
||||||
method: Pleroma.Captcha.Native
|
method: Pleroma.Captcha.Kocaptcha
|
||||||
|
|
||||||
|
config :pleroma, :hackney_pools,
|
||||||
|
federation: [
|
||||||
|
max_connections: 50,
|
||||||
|
timeout: 150_000
|
||||||
|
],
|
||||||
|
media: [
|
||||||
|
max_connections: 50,
|
||||||
|
timeout: 150_000
|
||||||
|
],
|
||||||
|
upload: [
|
||||||
|
max_connections: 25,
|
||||||
|
timeout: 300_000
|
||||||
|
]
|
||||||
|
|
||||||
config :pleroma, Pleroma.Captcha.Kocaptcha, endpoint: "https://captcha.kotobank.ch"
|
config :pleroma, Pleroma.Captcha.Kocaptcha, endpoint: "https://captcha.kotobank.ch"
|
||||||
|
|
||||||
|
@ -61,35 +76,35 @@
|
||||||
config :pleroma, Pleroma.Upload,
|
config :pleroma, Pleroma.Upload,
|
||||||
uploader: Pleroma.Uploaders.Local,
|
uploader: Pleroma.Uploaders.Local,
|
||||||
filters: [Pleroma.Upload.Filter.Dedupe],
|
filters: [Pleroma.Upload.Filter.Dedupe],
|
||||||
link_name: false,
|
link_name: true,
|
||||||
proxy_remote: false,
|
proxy_remote: false,
|
||||||
filename_display_max_length: 30,
|
proxy_opts: [
|
||||||
default_description: nil,
|
redirect_on_failure: false,
|
||||||
base_url: nil
|
max_body_length: 25 * 1_048_576,
|
||||||
|
http: [
|
||||||
|
follow_redirect: true,
|
||||||
|
pool: :upload
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads"
|
config :pleroma, Pleroma.Uploaders.Local, uploads: "uploads"
|
||||||
|
|
||||||
config :pleroma, Pleroma.Uploaders.S3,
|
config :pleroma, Pleroma.Uploaders.S3,
|
||||||
bucket: nil,
|
bucket: nil,
|
||||||
bucket_namespace: nil,
|
public_endpoint: "https://s3.amazonaws.com"
|
||||||
truncated_namespace: nil,
|
|
||||||
streaming_enabled: true
|
|
||||||
|
|
||||||
config :ex_aws, :s3,
|
config :pleroma, Pleroma.Uploaders.MDII,
|
||||||
# host: "s3.wasabisys.com", # required if not Amazon AWS
|
cgi: "https://mdii.sakura.ne.jp/mdii-post.cgi",
|
||||||
access_key_id: nil,
|
files: "https://mdii.sakura.ne.jp"
|
||||||
secret_access_key: nil,
|
|
||||||
# region: "us-east-1", # may be required for Amazon AWS
|
|
||||||
scheme: "https://"
|
|
||||||
|
|
||||||
config :pleroma, :emoji,
|
config :pleroma, :emoji,
|
||||||
shortcode_globs: ["/emoji/custom/**/*.png"],
|
shortcode_globs: ["/emoji/custom/**/*.png"],
|
||||||
pack_extensions: [".png", ".gif"],
|
pack_extensions: [".png", ".gif"],
|
||||||
groups: [
|
groups: [
|
||||||
|
# Put groups that have higher priority than defaults here. Example in `docs/config/custom_emoji.md`
|
||||||
Custom: ["/emoji/*.png", "/emoji/**/*.png"]
|
Custom: ["/emoji/*.png", "/emoji/**/*.png"]
|
||||||
],
|
],
|
||||||
default_manifest: "https://git.pleroma.social/pleroma/emoji-index/raw/master/index.json",
|
default_manifest: "https://git.pleroma.social/pleroma/emoji-index/raw/master/index.json"
|
||||||
shared_pack_cache_seconds_per_file: 60
|
|
||||||
|
|
||||||
config :pleroma, :uri_schemes,
|
config :pleroma, :uri_schemes,
|
||||||
valid_schemes: [
|
valid_schemes: [
|
||||||
|
@ -98,7 +113,6 @@
|
||||||
"dat",
|
"dat",
|
||||||
"dweb",
|
"dweb",
|
||||||
"gopher",
|
"gopher",
|
||||||
"hyper",
|
|
||||||
"ipfs",
|
"ipfs",
|
||||||
"ipns",
|
"ipns",
|
||||||
"irc",
|
"irc",
|
||||||
|
@ -123,6 +137,7 @@
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
|
instrumenters: [Pleroma.Web.Endpoint.Instrumenter],
|
||||||
url: [host: "localhost"],
|
url: [host: "localhost"],
|
||||||
http: [
|
http: [
|
||||||
ip: {127, 0, 0, 1},
|
ip: {127, 0, 0, 1},
|
||||||
|
@ -139,10 +154,9 @@
|
||||||
],
|
],
|
||||||
protocol: "https",
|
protocol: "https",
|
||||||
secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl",
|
secret_key_base: "aK4Abxf29xU9TTDKre9coZPUgevcVCFQJe/5xP/7Lt4BEif6idBIbjupVbOrbKxl",
|
||||||
live_view: [signing_salt: "U5ELgdEwTD3n1+D5s0rY0AMg8/y1STxZ3Zvsl3bWh+oBcGrYdil0rXqPMRd3Glcq"],
|
|
||||||
signing_salt: "CqaoopA2",
|
signing_salt: "CqaoopA2",
|
||||||
render_errors: [view: Pleroma.Web.ErrorView, accepts: ~w(json)],
|
render_errors: [view: Pleroma.Web.ErrorView, accepts: ~w(json)],
|
||||||
pubsub_server: Pleroma.PubSub,
|
pubsub: [name: Pleroma.PubSub, adapter: Phoenix.PubSub.PG2],
|
||||||
secure_cookie_flag: true,
|
secure_cookie_flag: true,
|
||||||
extra_cookie_attrs: [
|
extra_cookie_attrs: [
|
||||||
"SameSite=Lax"
|
"SameSite=Lax"
|
||||||
|
@ -150,8 +164,7 @@
|
||||||
|
|
||||||
# Configures Elixir's Logger
|
# Configures Elixir's Logger
|
||||||
config :logger, :console,
|
config :logger, :console,
|
||||||
level: :debug,
|
format: "$time $metadata[$level] $message\n",
|
||||||
format: "\n$time $metadata[$level] $message\n",
|
|
||||||
metadata: [:request_id]
|
metadata: [:request_id]
|
||||||
|
|
||||||
config :logger, :ex_syslogger,
|
config :logger, :ex_syslogger,
|
||||||
|
@ -160,6 +173,11 @@
|
||||||
format: "$metadata[$level] $message",
|
format: "$metadata[$level] $message",
|
||||||
metadata: [:request_id]
|
metadata: [:request_id]
|
||||||
|
|
||||||
|
config :quack,
|
||||||
|
level: :warn,
|
||||||
|
meta: [:all],
|
||||||
|
webhook_url: "https://hooks.slack.com/services/YOUR-KEY-HERE"
|
||||||
|
|
||||||
config :mime, :types, %{
|
config :mime, :types, %{
|
||||||
"application/xml" => ["xml"],
|
"application/xml" => ["xml"],
|
||||||
"application/xrd+xml" => ["xrd+xml"],
|
"application/xrd+xml" => ["xrd+xml"],
|
||||||
|
@ -174,19 +192,21 @@
|
||||||
config :pleroma, :http,
|
config :pleroma, :http,
|
||||||
proxy_url: nil,
|
proxy_url: nil,
|
||||||
send_user_agent: true,
|
send_user_agent: true,
|
||||||
user_agent: :default,
|
adapter: [
|
||||||
adapter: []
|
ssl_options: [
|
||||||
|
# Workaround for remote server certificate chain issues
|
||||||
|
partial_chain: &:hackney_connect.partial_chain/1,
|
||||||
|
# We don't support TLS v1.3 yet
|
||||||
|
versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
config :pleroma, :instance,
|
config :pleroma, :instance,
|
||||||
name: "Pleroma",
|
name: "Pleroma",
|
||||||
email: "example@example.com",
|
email: "example@example.com",
|
||||||
notify_email: "noreply@example.com",
|
notify_email: "noreply@example.com",
|
||||||
description: "Pleroma: An efficient and flexible fediverse server",
|
description: "A Pleroma instance, an alternative fediverse server",
|
||||||
short_description: "",
|
|
||||||
background_image: "/images/city.jpg",
|
|
||||||
instance_thumbnail: "/instance/thumbnail.jpeg",
|
|
||||||
limit: 5_000,
|
limit: 5_000,
|
||||||
description_limit: 5_000,
|
|
||||||
remote_limit: 100_000,
|
remote_limit: 100_000,
|
||||||
upload_limit: 16_000_000,
|
upload_limit: 16_000_000,
|
||||||
avatar_upload_limit: 2_000_000,
|
avatar_upload_limit: 2_000_000,
|
||||||
|
@ -199,18 +219,19 @@
|
||||||
max_expiration: 365 * 24 * 60 * 60
|
max_expiration: 365 * 24 * 60 * 60
|
||||||
},
|
},
|
||||||
registrations_open: true,
|
registrations_open: true,
|
||||||
invites_enabled: false,
|
|
||||||
account_activation_required: false,
|
|
||||||
account_approval_required: false,
|
|
||||||
federating: true,
|
federating: true,
|
||||||
federation_incoming_replies_max_depth: 100,
|
federation_incoming_replies_max_depth: 100,
|
||||||
federation_reachability_timeout_days: 7,
|
federation_reachability_timeout_days: 7,
|
||||||
federation_publisher_modules: [
|
federation_publisher_modules: [
|
||||||
Pleroma.Web.ActivityPub.Publisher
|
Pleroma.Web.ActivityPub.Publisher,
|
||||||
|
Pleroma.Web.Websub,
|
||||||
|
Pleroma.Web.Salmon
|
||||||
],
|
],
|
||||||
allow_relay: true,
|
allow_relay: true,
|
||||||
|
rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy,
|
||||||
public: true,
|
public: true,
|
||||||
quarantined_instances: [],
|
quarantined_instances: [],
|
||||||
|
managed_config: true,
|
||||||
static_dir: "instance/static/",
|
static_dir: "instance/static/",
|
||||||
allowed_post_formats: [
|
allowed_post_formats: [
|
||||||
"text/plain",
|
"text/plain",
|
||||||
|
@ -218,87 +239,20 @@
|
||||||
"text/markdown",
|
"text/markdown",
|
||||||
"text/bbcode"
|
"text/bbcode"
|
||||||
],
|
],
|
||||||
|
mrf_transparency: true,
|
||||||
|
mrf_transparency_exclusions: [],
|
||||||
autofollowed_nicknames: [],
|
autofollowed_nicknames: [],
|
||||||
autofollowing_nicknames: [],
|
|
||||||
max_pinned_statuses: 1,
|
max_pinned_statuses: 1,
|
||||||
attachment_links: false,
|
no_attachment_links: false,
|
||||||
|
welcome_user_nickname: nil,
|
||||||
|
welcome_message: nil,
|
||||||
max_report_comment_size: 1000,
|
max_report_comment_size: 1000,
|
||||||
report_strip_status: true,
|
|
||||||
safe_dm_mentions: false,
|
safe_dm_mentions: false,
|
||||||
healthcheck: false,
|
healthcheck: false,
|
||||||
remote_post_retention_days: 90,
|
remote_post_retention_days: 90,
|
||||||
skip_thread_containment: true,
|
skip_thread_containment: true,
|
||||||
limit_to_local_content: :unauthenticated,
|
limit_to_local_content: :unauthenticated,
|
||||||
user_bio_length: 5000,
|
dynamic_configuration: false
|
||||||
user_name_length: 100,
|
|
||||||
max_account_fields: 10,
|
|
||||||
max_remote_account_fields: 20,
|
|
||||||
account_field_name_length: 512,
|
|
||||||
account_field_value_length: 2048,
|
|
||||||
registration_reason_length: 500,
|
|
||||||
external_user_synchronization: true,
|
|
||||||
extended_nickname_format: true,
|
|
||||||
cleanup_attachments: false,
|
|
||||||
multi_factor_authentication: [
|
|
||||||
totp: [
|
|
||||||
# digits 6 or 8
|
|
||||||
digits: 6,
|
|
||||||
period: 30
|
|
||||||
],
|
|
||||||
backup_codes: [
|
|
||||||
number: 5,
|
|
||||||
length: 16
|
|
||||||
]
|
|
||||||
],
|
|
||||||
show_reactions: true,
|
|
||||||
password_reset_token_validity: 60 * 60 * 24,
|
|
||||||
profile_directory: true,
|
|
||||||
admin_privileges: [
|
|
||||||
:users_read,
|
|
||||||
:users_manage_invites,
|
|
||||||
:users_manage_activation_state,
|
|
||||||
:users_manage_tags,
|
|
||||||
:users_manage_credentials,
|
|
||||||
:users_delete,
|
|
||||||
:messages_read,
|
|
||||||
:messages_delete,
|
|
||||||
:instances_delete,
|
|
||||||
:reports_manage_reports,
|
|
||||||
:moderation_log_read,
|
|
||||||
:announcements_manage_announcements,
|
|
||||||
:emoji_manage_emoji,
|
|
||||||
:statistics_read
|
|
||||||
],
|
|
||||||
moderator_privileges: [:messages_delete, :reports_manage_reports],
|
|
||||||
max_endorsed_users: 20,
|
|
||||||
birthday_required: false,
|
|
||||||
birthday_min_age: 0,
|
|
||||||
max_media_attachments: 1_000
|
|
||||||
|
|
||||||
config :pleroma, :welcome,
|
|
||||||
direct_message: [
|
|
||||||
enabled: false,
|
|
||||||
sender_nickname: nil,
|
|
||||||
message: nil
|
|
||||||
],
|
|
||||||
chat_message: [
|
|
||||||
enabled: false,
|
|
||||||
sender_nickname: nil,
|
|
||||||
message: nil
|
|
||||||
],
|
|
||||||
email: [
|
|
||||||
enabled: false,
|
|
||||||
sender: nil,
|
|
||||||
subject: "Welcome to <%= instance_name %>",
|
|
||||||
html: "Welcome to <%= instance_name %>",
|
|
||||||
text: "Welcome to <%= instance_name %>"
|
|
||||||
]
|
|
||||||
|
|
||||||
config :pleroma, :feed,
|
|
||||||
post_title: %{
|
|
||||||
max_length: 100,
|
|
||||||
omission: "..."
|
|
||||||
}
|
|
||||||
|
|
||||||
config :pleroma, :markup,
|
config :pleroma, :markup,
|
||||||
# XXX - unfortunately, inline images must be enabled by default right now, because
|
# XXX - unfortunately, inline images must be enabled by default right now, because
|
||||||
|
@ -308,39 +262,29 @@
|
||||||
allow_tables: false,
|
allow_tables: false,
|
||||||
allow_fonts: false,
|
allow_fonts: false,
|
||||||
scrub_policy: [
|
scrub_policy: [
|
||||||
Pleroma.HTML.Scrubber.Default,
|
Pleroma.HTML.Transform.MediaProxy,
|
||||||
Pleroma.HTML.Transform.MediaProxy
|
Pleroma.HTML.Scrubber.Default
|
||||||
]
|
]
|
||||||
|
|
||||||
config :pleroma, :frontend_configurations,
|
config :pleroma, :frontend_configurations,
|
||||||
pleroma_fe: %{
|
pleroma_fe: %{
|
||||||
alwaysShowSubjectInput: true,
|
|
||||||
background: "/images/city.jpg",
|
|
||||||
collapseMessageWithSubject: false,
|
|
||||||
disableChat: false,
|
|
||||||
greentext: false,
|
|
||||||
hideFilteredStatuses: false,
|
|
||||||
hideMutedPosts: false,
|
|
||||||
hidePostStats: false,
|
|
||||||
hideSitename: false,
|
|
||||||
hideUserStats: false,
|
|
||||||
loginMethod: "password",
|
|
||||||
logo: "/static/logo.svg",
|
|
||||||
logoMargin: ".1em",
|
|
||||||
logoMask: true,
|
|
||||||
minimalScopesMode: false,
|
|
||||||
noAttachmentLinks: false,
|
|
||||||
nsfwCensorImage: "",
|
|
||||||
postContentType: "text/plain",
|
|
||||||
redirectRootLogin: "/main/friends",
|
|
||||||
redirectRootNoLogin: "/main/all",
|
|
||||||
scopeCopy: true,
|
|
||||||
sidebarRight: false,
|
|
||||||
showFeaturesPanel: true,
|
|
||||||
showInstanceSpecificPanel: false,
|
|
||||||
subjectLineBehavior: "email",
|
|
||||||
theme: "pleroma-dark",
|
theme: "pleroma-dark",
|
||||||
webPushNotifications: false
|
logo: "/static/logo.png",
|
||||||
|
background: "/images/city.jpg",
|
||||||
|
redirectRootNoLogin: "/main/all",
|
||||||
|
redirectRootLogin: "/main/friends",
|
||||||
|
showInstanceSpecificPanel: true,
|
||||||
|
scopeOptionsEnabled: false,
|
||||||
|
formattingOptionsEnabled: false,
|
||||||
|
collapseMessageWithSubject: false,
|
||||||
|
hidePostStats: false,
|
||||||
|
hideUserStats: false,
|
||||||
|
scopeCopy: true,
|
||||||
|
subjectLineBehavior: "email",
|
||||||
|
alwaysShowSubjectInput: true
|
||||||
|
},
|
||||||
|
masto_fe: %{
|
||||||
|
showInstanceSpecificPanel: true
|
||||||
}
|
}
|
||||||
|
|
||||||
config :pleroma, :assets,
|
config :pleroma, :assets,
|
||||||
|
@ -356,28 +300,10 @@
|
||||||
],
|
],
|
||||||
default_mascot: :pleroma_fox_tan
|
default_mascot: :pleroma_fox_tan
|
||||||
|
|
||||||
config :pleroma, :manifest,
|
|
||||||
icons: [
|
|
||||||
%{
|
|
||||||
src: "/static/logo.svg",
|
|
||||||
type: "image/svg+xml"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
theme_color: "#282c37",
|
|
||||||
background_color: "#191b22"
|
|
||||||
|
|
||||||
config :pleroma, :activitypub,
|
config :pleroma, :activitypub,
|
||||||
unfollow_blocked: true,
|
unfollow_blocked: true,
|
||||||
outgoing_blocks: true,
|
outgoing_blocks: true,
|
||||||
blockers_visible: true,
|
follow_handshake_timeout: 500
|
||||||
follow_handshake_timeout: 500,
|
|
||||||
note_replies_output_limit: 5,
|
|
||||||
sign_object_fetches: true,
|
|
||||||
authorized_fetch_mode: false
|
|
||||||
|
|
||||||
config :pleroma, :streamer,
|
|
||||||
workers: 3,
|
|
||||||
overflow_workers: 2
|
|
||||||
|
|
||||||
config :pleroma, :user, deny_follow_blocked: true
|
config :pleroma, :user, deny_follow_blocked: true
|
||||||
|
|
||||||
|
@ -397,59 +323,31 @@
|
||||||
federated_timeline_removal: [],
|
federated_timeline_removal: [],
|
||||||
report_removal: [],
|
report_removal: [],
|
||||||
reject: [],
|
reject: [],
|
||||||
followers_only: [],
|
|
||||||
accept: [],
|
accept: [],
|
||||||
avatar_removal: [],
|
avatar_removal: [],
|
||||||
banner_removal: [],
|
banner_removal: []
|
||||||
reject_deletes: []
|
|
||||||
|
|
||||||
config :pleroma, :mrf_keyword,
|
config :pleroma, :mrf_keyword,
|
||||||
reject: [],
|
reject: [],
|
||||||
federated_timeline_removal: [],
|
federated_timeline_removal: [],
|
||||||
replace: []
|
replace: []
|
||||||
|
|
||||||
config :pleroma, :mrf_hashtag,
|
|
||||||
sensitive: ["nsfw"],
|
|
||||||
reject: [],
|
|
||||||
federated_timeline_removal: []
|
|
||||||
|
|
||||||
config :pleroma, :mrf_subchain, match_actor: %{}
|
config :pleroma, :mrf_subchain, match_actor: %{}
|
||||||
|
|
||||||
config :pleroma, :mrf_activity_expiration, days: 365
|
|
||||||
|
|
||||||
config :pleroma, :mrf_vocabulary,
|
config :pleroma, :mrf_vocabulary,
|
||||||
accept: [],
|
accept: [],
|
||||||
reject: []
|
reject: []
|
||||||
|
|
||||||
# threshold of 7 days
|
|
||||||
config :pleroma, :mrf_object_age,
|
|
||||||
threshold: 604_800,
|
|
||||||
actions: [:delist, :strip_followers]
|
|
||||||
|
|
||||||
config :pleroma, :mrf_follow_bot, follower_nickname: nil
|
|
||||||
|
|
||||||
config :pleroma, :rich_media,
|
config :pleroma, :rich_media,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ignore_hosts: [],
|
ignore_hosts: [],
|
||||||
ignore_tld: ["local", "localdomain", "lan"],
|
ignore_tld: ["local", "localdomain", "lan"]
|
||||||
parsers: [
|
|
||||||
Pleroma.Web.RichMedia.Parsers.TwitterCard,
|
|
||||||
Pleroma.Web.RichMedia.Parsers.OEmbed
|
|
||||||
],
|
|
||||||
failure_backoff: 60_000,
|
|
||||||
ttl_setters: [Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl]
|
|
||||||
|
|
||||||
config :pleroma, :media_proxy,
|
config :pleroma, :media_proxy,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
invalidation: [
|
|
||||||
enabled: false,
|
|
||||||
provider: Pleroma.Web.MediaProxy.Invalidation.Script
|
|
||||||
],
|
|
||||||
proxy_opts: [
|
proxy_opts: [
|
||||||
redirect_on_failure: false,
|
redirect_on_failure: false,
|
||||||
max_body_length: 25 * 1_048_576,
|
max_body_length: 25 * 1_048_576,
|
||||||
# Note: max_read_duration defaults to Pleroma.ReverseProxy.max_read_duration_default/1
|
|
||||||
max_read_duration: 30_000,
|
|
||||||
http: [
|
http: [
|
||||||
follow_redirect: true,
|
follow_redirect: true,
|
||||||
pool: :media
|
pool: :media
|
||||||
|
@ -457,32 +355,9 @@
|
||||||
],
|
],
|
||||||
whitelist: []
|
whitelist: []
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Http,
|
config :pleroma, :chat, enabled: true
|
||||||
method: :purge,
|
|
||||||
headers: [],
|
|
||||||
options: []
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.MediaProxy.Invalidation.Script,
|
config :phoenix, :format_encoders, json: Jason
|
||||||
script_path: nil,
|
|
||||||
url_format: nil
|
|
||||||
|
|
||||||
# Note: media preview proxy depends on media proxy to be enabled
|
|
||||||
config :pleroma, :media_preview_proxy,
|
|
||||||
enabled: false,
|
|
||||||
thumbnail_max_width: 600,
|
|
||||||
thumbnail_max_height: 600,
|
|
||||||
image_quality: 85,
|
|
||||||
min_content_length: 100 * 1024
|
|
||||||
|
|
||||||
config :pleroma, :shout,
|
|
||||||
enabled: true,
|
|
||||||
limit: 5_000
|
|
||||||
|
|
||||||
config :phoenix, :format_encoders, json: Jason, "activity+json": Jason
|
|
||||||
|
|
||||||
config :phoenix, :json_library, Jason
|
|
||||||
|
|
||||||
config :phoenix, :filter_parameters, ["password", "confirm"]
|
|
||||||
|
|
||||||
config :pleroma, :gopher,
|
config :pleroma, :gopher,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
@ -492,14 +367,18 @@
|
||||||
config :pleroma, Pleroma.Web.Metadata,
|
config :pleroma, Pleroma.Web.Metadata,
|
||||||
providers: [
|
providers: [
|
||||||
Pleroma.Web.Metadata.Providers.OpenGraph,
|
Pleroma.Web.Metadata.Providers.OpenGraph,
|
||||||
Pleroma.Web.Metadata.Providers.TwitterCard
|
Pleroma.Web.Metadata.Providers.TwitterCard,
|
||||||
|
Pleroma.Web.Metadata.Providers.RelMe
|
||||||
],
|
],
|
||||||
unfurl_nsfw: false
|
unfurl_nsfw: false
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Preload,
|
config :pleroma, :suggestions,
|
||||||
providers: [
|
enabled: false,
|
||||||
Pleroma.Web.Preload.Providers.Instance
|
third_party_engine:
|
||||||
]
|
"http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-suggestions-api.cgi?{{host}}+{{user}}",
|
||||||
|
timeout: 300_000,
|
||||||
|
limit: 40,
|
||||||
|
web: "https://vinayaka.distsn.org"
|
||||||
|
|
||||||
config :pleroma, :http_security,
|
config :pleroma, :http_security,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -553,58 +432,39 @@
|
||||||
"user-search",
|
"user-search",
|
||||||
"user_exists",
|
"user_exists",
|
||||||
"users",
|
"users",
|
||||||
"web",
|
"web"
|
||||||
"verify_credentials",
|
]
|
||||||
"update_credentials",
|
|
||||||
"relationships",
|
|
||||||
"search",
|
|
||||||
"confirmation_resend",
|
|
||||||
"mfa"
|
|
||||||
],
|
|
||||||
email_blacklist: []
|
|
||||||
|
|
||||||
config :pleroma, Oban,
|
config :pleroma, Pleroma.Web.Federator.RetryQueue,
|
||||||
repo: Pleroma.Repo,
|
enabled: false,
|
||||||
log: false,
|
max_jobs: 20,
|
||||||
queues: [
|
initial_timeout: 30,
|
||||||
activity_expiration: 10,
|
max_retries: 5
|
||||||
token_expiration: 5,
|
|
||||||
filter_expiration: 1,
|
config :pleroma_job_queue, :queues,
|
||||||
backup: 1,
|
federator_incoming: 50,
|
||||||
federator_incoming: 5,
|
federator_outgoing: 50,
|
||||||
federator_outgoing: 5,
|
|
||||||
ingestion_queue: 50,
|
|
||||||
web_push: 50,
|
web_push: 50,
|
||||||
mailer: 10,
|
mailer: 10,
|
||||||
transmogrifier: 20,
|
transmogrifier: 20,
|
||||||
scheduled_activities: 10,
|
scheduled_activities: 10,
|
||||||
poll_notifications: 10,
|
background: 5
|
||||||
background: 5,
|
|
||||||
remote_fetcher: 2,
|
|
||||||
attachments_cleanup: 1,
|
|
||||||
new_users_digest: 1,
|
|
||||||
mute_expire: 5
|
|
||||||
],
|
|
||||||
plugins: [Oban.Plugins.Pruner],
|
|
||||||
crontab: [
|
|
||||||
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
|
|
||||||
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}
|
|
||||||
]
|
|
||||||
|
|
||||||
config :pleroma, :workers,
|
config :pleroma, :fetch_initial_posts,
|
||||||
retries: [
|
enabled: false,
|
||||||
federator_incoming: 5,
|
pages: 5
|
||||||
federator_outgoing: 5
|
|
||||||
]
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Formatter,
|
config :auto_linker,
|
||||||
class: false,
|
opts: [
|
||||||
rel: "ugc",
|
scheme: true,
|
||||||
new_window: false,
|
|
||||||
truncate: false,
|
|
||||||
strip_prefix: false,
|
|
||||||
extra: true,
|
extra: true,
|
||||||
validate_tld: :no_scheme
|
# TODO: Set to :no_scheme when it works properly
|
||||||
|
validate_tld: true,
|
||||||
|
class: false,
|
||||||
|
strip_prefix: false,
|
||||||
|
new_window: false,
|
||||||
|
rel: false
|
||||||
|
]
|
||||||
|
|
||||||
config :pleroma, :ldap,
|
config :pleroma, :ldap,
|
||||||
enabled: System.get_env("LDAP_ENABLED") == "true",
|
enabled: System.get_env("LDAP_ENABLED") == "true",
|
||||||
|
@ -640,248 +500,31 @@
|
||||||
|
|
||||||
config :pleroma, :auth, oauth_consumer_strategies: oauth_consumer_strategies
|
config :pleroma, :auth, oauth_consumer_strategies: oauth_consumer_strategies
|
||||||
|
|
||||||
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Sendmail, enabled: false
|
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Sendmail
|
||||||
|
|
||||||
config :pleroma, Pleroma.Emails.UserEmail,
|
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, path: "/api/pleroma/app_metrics"
|
||||||
logo: nil,
|
|
||||||
styling: %{
|
|
||||||
link_color: "#d8a070",
|
|
||||||
background_color: "#2C3645",
|
|
||||||
content_background_color: "#1B2635",
|
|
||||||
header_color: "#d8a070",
|
|
||||||
text_color: "#b9b9ba",
|
|
||||||
text_muted_color: "#b9b9ba"
|
|
||||||
}
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: false
|
|
||||||
|
|
||||||
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter,
|
|
||||||
enabled: false,
|
|
||||||
auth: false,
|
|
||||||
ip_whitelist: [],
|
|
||||||
path: "/api/pleroma/app_metrics",
|
|
||||||
format: :text
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.ScheduledActivity,
|
config :pleroma, Pleroma.ScheduledActivity,
|
||||||
daily_user_limit: 25,
|
daily_user_limit: 25,
|
||||||
total_user_limit: 300,
|
total_user_limit: 300,
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
config :pleroma, :email_notifications,
|
|
||||||
digest: %{
|
|
||||||
active: false,
|
|
||||||
interval: 7,
|
|
||||||
inactivity_threshold: 7
|
|
||||||
}
|
|
||||||
|
|
||||||
config :pleroma, :oauth2,
|
config :pleroma, :oauth2,
|
||||||
token_expires_in: 3600 * 24 * 365 * 100,
|
token_expires_in: 600,
|
||||||
issue_new_refresh_token: true,
|
issue_new_refresh_token: true,
|
||||||
clean_expired_tokens: false
|
clean_expired_tokens: false,
|
||||||
|
clean_expired_tokens_interval: 86_400_000
|
||||||
|
|
||||||
config :pleroma, :database, rum_enabled: false
|
config :pleroma, :database, rum_enabled: false
|
||||||
|
|
||||||
config :pleroma, :features, improved_hashtag_timeline: :auto
|
|
||||||
|
|
||||||
config :pleroma, :populate_hashtags_table, fault_rate_allowance: 0.01
|
|
||||||
|
|
||||||
config :pleroma, :delete_context_objects, fault_rate_allowance: 0.01
|
|
||||||
|
|
||||||
config :pleroma, :env, Mix.env()
|
config :pleroma, :env, Mix.env()
|
||||||
|
|
||||||
config :http_signatures,
|
config :http_signatures,
|
||||||
adapter: Pleroma.Signature
|
adapter: Pleroma.Signature
|
||||||
|
|
||||||
config :pleroma, :rate_limit,
|
config :pleroma, :rate_limit,
|
||||||
authentication: {60_000, 15},
|
|
||||||
timeline: {500, 3},
|
|
||||||
search: [{1000, 10}, {1000, 30}],
|
search: [{1000, 10}, {1000, 30}],
|
||||||
app_account_creation: {1_800_000, 25},
|
app_account_creation: {1_800_000, 25}
|
||||||
relations_actions: {10_000, 10},
|
|
||||||
relation_id_action: {60_000, 2},
|
|
||||||
statuses_actions: {10_000, 15},
|
|
||||||
status_id_action: {60_000, 3},
|
|
||||||
password_reset: {1_800_000, 5},
|
|
||||||
account_confirmation_resend: {8_640_000, 5},
|
|
||||||
ap_routes: {60_000, 15}
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Workers.PurgeExpiredActivity, enabled: true, min_lifetime: 600
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Plugs.RemoteIp,
|
|
||||||
enabled: true,
|
|
||||||
headers: ["x-forwarded-for"],
|
|
||||||
proxies: [],
|
|
||||||
reserved: [
|
|
||||||
"127.0.0.0/8",
|
|
||||||
"::1/128",
|
|
||||||
"fc00::/7",
|
|
||||||
"10.0.0.0/8",
|
|
||||||
"172.16.0.0/12",
|
|
||||||
"192.168.0.0/16"
|
|
||||||
]
|
|
||||||
|
|
||||||
config :pleroma, :static_fe, enabled: false
|
|
||||||
|
|
||||||
# Example of frontend configuration
|
|
||||||
# This example will make us serve the primary frontend from the
|
|
||||||
# frontends directory within your `:pleroma, :instance, static_dir`.
|
|
||||||
# e.g., instance/static/frontends/pleroma/develop/
|
|
||||||
#
|
|
||||||
# With no frontend configuration, the bundled files from the `static` directory will
|
|
||||||
# be used.
|
|
||||||
#
|
|
||||||
# config :pleroma, :frontends,
|
|
||||||
# primary: %{"name" => "pleroma-fe", "ref" => "develop"},
|
|
||||||
# admin: %{"name" => "admin-fe", "ref" => "stable"},
|
|
||||||
# available: %{...}
|
|
||||||
|
|
||||||
config :pleroma, :frontends,
|
|
||||||
available: %{
|
|
||||||
"kenoma" => %{
|
|
||||||
"name" => "kenoma",
|
|
||||||
"git" => "https://git.pleroma.social/lambadalambda/kenoma",
|
|
||||||
"build_url" =>
|
|
||||||
"https://git.pleroma.social/lambadalambda/kenoma/-/jobs/artifacts/${ref}/download?job=build",
|
|
||||||
"ref" => "master"
|
|
||||||
},
|
|
||||||
"pleroma-fe" => %{
|
|
||||||
"name" => "pleroma-fe",
|
|
||||||
"git" => "https://git.pleroma.social/pleroma/pleroma-fe",
|
|
||||||
"build_url" =>
|
|
||||||
"https://git.pleroma.social/pleroma/pleroma-fe/-/jobs/artifacts/${ref}/download?job=build",
|
|
||||||
"ref" => "develop"
|
|
||||||
},
|
|
||||||
"fedi-fe" => %{
|
|
||||||
"name" => "fedi-fe",
|
|
||||||
"git" => "https://git.pleroma.social/pleroma/fedi-fe",
|
|
||||||
"build_url" =>
|
|
||||||
"https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build_release",
|
|
||||||
"ref" => "master",
|
|
||||||
"custom-http-headers" => [
|
|
||||||
{"service-worker-allowed", "/"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"admin-fe" => %{
|
|
||||||
"name" => "admin-fe",
|
|
||||||
"git" => "https://git.pleroma.social/pleroma/admin-fe",
|
|
||||||
"build_url" =>
|
|
||||||
"https://git.pleroma.social/pleroma/admin-fe/-/jobs/artifacts/${ref}/download?job=build",
|
|
||||||
"ref" => "develop"
|
|
||||||
},
|
|
||||||
"soapbox" => %{
|
|
||||||
"name" => "soapbox",
|
|
||||||
"git" => "https://gitlab.com/soapbox-pub/soapbox",
|
|
||||||
"build_url" =>
|
|
||||||
"https://gitlab.com/soapbox-pub/soapbox/-/jobs/artifacts/${ref}/download?job=build-production",
|
|
||||||
"ref" => "v3.0.0-beta.1",
|
|
||||||
"build_dir" => "static"
|
|
||||||
},
|
|
||||||
"glitch-lily" => %{
|
|
||||||
"name" => "glitch-lily",
|
|
||||||
"git" => "https://lily-is.land/infra/glitch-lily",
|
|
||||||
"build_url" =>
|
|
||||||
"https://lily-is.land/infra/glitch-lily/-/jobs/artifacts/${ref}/download?job=build",
|
|
||||||
"ref" => "servant",
|
|
||||||
"build_dir" => "public"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config :pleroma, :web_cache_ttl,
|
|
||||||
activity_pub: nil,
|
|
||||||
activity_pub_question: 30_000
|
|
||||||
|
|
||||||
config :pleroma, :modules, runtime_dir: "instance/modules"
|
|
||||||
|
|
||||||
config :pleroma, configurable_from_database: false
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
|
||||||
parameters: [gin_fuzzy_search_limit: "500"],
|
|
||||||
prepare: :unnamed
|
|
||||||
|
|
||||||
config :pleroma, :connections_pool,
|
|
||||||
reclaim_multiplier: 0.1,
|
|
||||||
connection_acquisition_wait: 250,
|
|
||||||
connection_acquisition_retries: 5,
|
|
||||||
max_connections: 250,
|
|
||||||
max_idle_time: 30_000,
|
|
||||||
retry: 0,
|
|
||||||
connect_timeout: 5_000
|
|
||||||
|
|
||||||
config :pleroma, :pools,
|
|
||||||
federation: [
|
|
||||||
size: 50,
|
|
||||||
max_waiting: 10,
|
|
||||||
recv_timeout: 10_000
|
|
||||||
],
|
|
||||||
media: [
|
|
||||||
size: 50,
|
|
||||||
max_waiting: 20,
|
|
||||||
recv_timeout: 15_000
|
|
||||||
],
|
|
||||||
upload: [
|
|
||||||
size: 25,
|
|
||||||
max_waiting: 5,
|
|
||||||
recv_timeout: 15_000
|
|
||||||
],
|
|
||||||
default: [
|
|
||||||
size: 10,
|
|
||||||
max_waiting: 2,
|
|
||||||
recv_timeout: 5_000
|
|
||||||
]
|
|
||||||
|
|
||||||
config :pleroma, :hackney_pools,
|
|
||||||
federation: [
|
|
||||||
max_connections: 50,
|
|
||||||
timeout: 150_000
|
|
||||||
],
|
|
||||||
media: [
|
|
||||||
max_connections: 50,
|
|
||||||
timeout: 150_000
|
|
||||||
],
|
|
||||||
upload: [
|
|
||||||
max_connections: 25,
|
|
||||||
timeout: 300_000
|
|
||||||
]
|
|
||||||
|
|
||||||
config :pleroma, :majic_pool, size: 2
|
|
||||||
|
|
||||||
private_instance? = :if_instance_is_private
|
|
||||||
|
|
||||||
config :pleroma, :restrict_unauthenticated,
|
|
||||||
timelines: %{local: private_instance?, federated: private_instance?},
|
|
||||||
profiles: %{local: private_instance?, remote: private_instance?},
|
|
||||||
activities: %{local: private_instance?, remote: private_instance?}
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
|
|
||||||
|
|
||||||
config :pleroma, :mrf,
|
|
||||||
policies: [Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy, Pleroma.Web.ActivityPub.MRF.TagPolicy],
|
|
||||||
transparency: true,
|
|
||||||
transparency_exclusions: []
|
|
||||||
|
|
||||||
config :tzdata, :http_client, Pleroma.HTTP.Tzdata
|
|
||||||
|
|
||||||
config :ex_aws, http_client: Pleroma.HTTP.ExAws
|
|
||||||
|
|
||||||
config :web_push_encryption, http_client: Pleroma.HTTP.WebPush
|
|
||||||
|
|
||||||
config :pleroma, :instances_favicons, enabled: false
|
|
||||||
|
|
||||||
config :floki, :html_parser, Floki.HTMLParser.FastHtml
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.PleromaAuthenticator
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.User.Backup,
|
|
||||||
purge_after_days: 30,
|
|
||||||
limit_days: 7,
|
|
||||||
dir: nil
|
|
||||||
|
|
||||||
config :pleroma, ConcurrentLimiter, [
|
|
||||||
{Pleroma.Web.RichMedia.Helpers, [max_running: 5, max_waiting: 5]},
|
|
||||||
{Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy, [max_running: 5, max_waiting: 5]}
|
|
||||||
]
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.WebFinger, domain: nil, update_nickname_on_user_fetch: true
|
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
||||||
import Config
|
use Mix.Config
|
||||||
|
|
||||||
# For development, we disable any cache and enable
|
# For development, we disable any cache and enable
|
||||||
# debugging and code reloading.
|
# debugging and code reloading.
|
||||||
|
@ -52,17 +52,10 @@
|
||||||
hostname: "localhost",
|
hostname: "localhost",
|
||||||
pool_size: 10
|
pool_size: 10
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true
|
|
||||||
|
|
||||||
# Reduce recompilation time
|
|
||||||
# https://dashbit.co/blog/speeding-up-re-compilation-of-elixir-projects
|
|
||||||
config :phoenix, :plug_init_mode, :runtime
|
|
||||||
|
|
||||||
if File.exists?("./config/dev.secret.exs") do
|
if File.exists?("./config/dev.secret.exs") do
|
||||||
import_config "dev.secret.exs"
|
import_config "dev.secret.exs"
|
||||||
else
|
else
|
||||||
IO.puts(
|
IO.puts(
|
||||||
:stderr,
|
|
||||||
"!!! RUNNING IN LOCALHOST DEV MODE! !!!\nFEDERATION WON'T WORK UNTIL YOU CONFIGURE A dev.secret.exs"
|
"!!! RUNNING IN LOCALHOST DEV MODE! !!!\nFEDERATION WON'T WORK UNTIL YOU CONFIGURE A dev.secret.exs"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
import Config
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
|
||||||
url: [host: System.get_env("DOMAIN", "localhost"), scheme: "https", port: 443],
|
|
||||||
http: [ip: {0, 0, 0, 0}, port: 4000]
|
|
||||||
|
|
||||||
config :pleroma, :instance,
|
|
||||||
name: System.get_env("INSTANCE_NAME", "Pleroma"),
|
|
||||||
email: System.get_env("ADMIN_EMAIL"),
|
|
||||||
notify_email: System.get_env("NOTIFY_EMAIL"),
|
|
||||||
limit: 5000,
|
|
||||||
registrations_open: false,
|
|
||||||
healthcheck: true
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
|
||||||
adapter: Ecto.Adapters.Postgres,
|
|
||||||
username: System.get_env("DB_USER", "pleroma"),
|
|
||||||
password: System.fetch_env!("DB_PASS"),
|
|
||||||
database: System.get_env("DB_NAME", "pleroma"),
|
|
||||||
hostname: System.get_env("DB_HOST", "db"),
|
|
||||||
port: System.get_env("DB_PORT", "5432"),
|
|
||||||
pool_size: 10
|
|
||||||
|
|
||||||
# Configure web push notifications
|
|
||||||
config :web_push_encryption, :vapid_details, subject: "mailto:#{System.get_env("NOTIFY_EMAIL")}"
|
|
||||||
|
|
||||||
config :pleroma, :database, rum_enabled: false
|
|
||||||
config :pleroma, :instance, static_dir: "/var/lib/pleroma/static"
|
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
|
|
||||||
|
|
||||||
# We can't store the secrets in this file, since this is baked into the docker image
|
|
||||||
if not File.exists?("/var/lib/pleroma/secret.exs") do
|
|
||||||
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
|
|
||||||
signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
|
|
||||||
{web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
|
|
||||||
|
|
||||||
secret_file =
|
|
||||||
EEx.eval_string(
|
|
||||||
"""
|
|
||||||
import Config
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
|
||||||
secret_key_base: "<%= secret %>",
|
|
||||||
signing_salt: "<%= signing_salt %>"
|
|
||||||
|
|
||||||
config :web_push_encryption, :vapid_details,
|
|
||||||
public_key: "<%= web_push_public_key %>",
|
|
||||||
private_key: "<%= web_push_private_key %>"
|
|
||||||
""",
|
|
||||||
secret: secret,
|
|
||||||
signing_salt: signing_salt,
|
|
||||||
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)
|
|
||||||
)
|
|
||||||
|
|
||||||
File.write("/var/lib/pleroma/secret.exs", secret_file)
|
|
||||||
end
|
|
||||||
|
|
||||||
import_config("/var/lib/pleroma/secret.exs")
|
|
||||||
|
|
||||||
# For additional user config
|
|
||||||
if File.exists?("/var/lib/pleroma/config.exs"),
|
|
||||||
do: import_config("/var/lib/pleroma/config.exs"),
|
|
||||||
else:
|
|
||||||
File.write("/var/lib/pleroma/config.exs", """
|
|
||||||
import Config
|
|
||||||
|
|
||||||
# For additional configuration outside of environmental variables
|
|
||||||
""")
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Config
|
use Mix.Config
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
http: [
|
http: [
|
||||||
|
|
|
@ -1,3 +1,30 @@
|
||||||
firefox, /emoji/Firefox.gif, Gif,Fun
|
firefox, /emoji/Firefox.gif, Gif,Fun
|
||||||
blank, /emoji/blank.png, Fun
|
blank, /emoji/blank.png, Fun
|
||||||
dinosaur, /emoji/dino walking.gif, Gif
|
f_00b, /emoji/f_00b.png
|
||||||
|
f_00b11b, /emoji/f_00b11b.png
|
||||||
|
f_00b33b, /emoji/f_00b33b.png
|
||||||
|
f_00h, /emoji/f_00h.png
|
||||||
|
f_00t, /emoji/f_00t.png
|
||||||
|
f_01b, /emoji/f_01b.png
|
||||||
|
f_03b, /emoji/f_03b.png
|
||||||
|
f_10b, /emoji/f_10b.png
|
||||||
|
f_11b, /emoji/f_11b.png
|
||||||
|
f_11b00b, /emoji/f_11b00b.png
|
||||||
|
f_11b22b, /emoji/f_11b22b.png
|
||||||
|
f_11h, /emoji/f_11h.png
|
||||||
|
f_11t, /emoji/f_11t.png
|
||||||
|
f_12b, /emoji/f_12b.png
|
||||||
|
f_21b, /emoji/f_21b.png
|
||||||
|
f_22b, /emoji/f_22b.png
|
||||||
|
f_22b11b, /emoji/f_22b11b.png
|
||||||
|
f_22b33b, /emoji/f_22b33b.png
|
||||||
|
f_22h, /emoji/f_22h.png
|
||||||
|
f_22t, /emoji/f_22t.png
|
||||||
|
f_23b, /emoji/f_23b.png
|
||||||
|
f_30b, /emoji/f_30b.png
|
||||||
|
f_32b, /emoji/f_32b.png
|
||||||
|
f_33b, /emoji/f_33b.png
|
||||||
|
f_33b00b, /emoji/f_33b00b.png
|
||||||
|
f_33b22b, /emoji/f_33b22b.png
|
||||||
|
f_33h, /emoji/f_33h.png
|
||||||
|
f_33t, /emoji/f_33t.png
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Config
|
use Mix.Config
|
||||||
|
|
||||||
# For production, we often load configuration from external
|
# For production, we often load configuration from external
|
||||||
# sources, such as your system environment. For this reason,
|
# sources, such as your system environment. For this reason,
|
||||||
|
@ -20,8 +20,7 @@
|
||||||
config :phoenix, serve_endpoints: true
|
config :phoenix, serve_endpoints: true
|
||||||
|
|
||||||
# Do not print debug messages in production
|
# Do not print debug messages in production
|
||||||
config :logger, :console, level: :info
|
config :logger, level: :warn
|
||||||
config :logger, :ex_syslogger, level: :info
|
|
||||||
|
|
||||||
# ## SSL Support
|
# ## SSL Support
|
||||||
#
|
#
|
||||||
|
@ -63,12 +62,7 @@
|
||||||
|
|
||||||
# Finally import the config/prod.secret.exs
|
# Finally import the config/prod.secret.exs
|
||||||
# which should be versioned separately.
|
# which should be versioned separately.
|
||||||
if File.exists?("./config/prod.secret.exs") do
|
|
||||||
import_config "prod.secret.exs"
|
import_config "prod.secret.exs"
|
||||||
else
|
|
||||||
"`config/prod.secret.exs` not found. You may want to create one by running `mix pleroma.instance gen`"
|
|
||||||
|> IO.warn([])
|
|
||||||
end
|
|
||||||
|
|
||||||
if File.exists?("./config/prod.exported_from_db.secret.exs"),
|
if File.exists?("./config/prod.exported_from_db.secret.exs"),
|
||||||
do: import_config("prod.exported_from_db.secret.exs")
|
do: import_config("prod.exported_from_db.secret.exs")
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import Config
|
||||||
|
|
||||||
|
config :pleroma, :instance, static_dir: "/var/lib/pleroma/static"
|
||||||
|
config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
|
||||||
|
|
||||||
|
config_path = System.get_env("PLEROMA_CONFIG_PATH") || "/etc/pleroma/config.exs"
|
||||||
|
|
||||||
|
if File.exists?(config_path) do
|
||||||
|
import_config config_path
|
||||||
|
else
|
||||||
|
warning = [
|
||||||
|
IO.ANSI.red(),
|
||||||
|
IO.ANSI.bright(),
|
||||||
|
"!!! #{config_path} not found! Please ensure it exists and that PLEROMA_CONFIG_PATH is unset or points to an existing file",
|
||||||
|
IO.ANSI.reset()
|
||||||
|
]
|
||||||
|
|
||||||
|
IO.puts(warning)
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
import Config
|
use Mix.Config
|
||||||
|
|
||||||
# We don't run a server during test. If one is required,
|
# We don't run a server during test. If one is required,
|
||||||
# you can enable the server option below.
|
# you can enable the server option below.
|
||||||
|
@ -15,30 +15,20 @@
|
||||||
method: Pleroma.Captcha.Mock
|
method: Pleroma.Captcha.Mock
|
||||||
|
|
||||||
# Print only warnings and errors during test
|
# Print only warnings and errors during test
|
||||||
config :logger, :console,
|
config :logger, level: :warn
|
||||||
level: :warn,
|
|
||||||
format: "\n[$level] $message\n"
|
|
||||||
|
|
||||||
config :pleroma, :auth, oauth_consumer_strategies: []
|
config :pleroma, :auth, oauth_consumer_strategies: []
|
||||||
|
|
||||||
config :pleroma, Pleroma.Upload,
|
config :pleroma, Pleroma.Upload, filters: [], link_name: false
|
||||||
filters: [],
|
|
||||||
link_name: false,
|
|
||||||
default_description: :filename
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
|
config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
|
||||||
|
|
||||||
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Test, enabled: true
|
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Test
|
||||||
|
|
||||||
config :pleroma, :instance,
|
config :pleroma, :instance,
|
||||||
email: "admin@example.com",
|
email: "admin@example.com",
|
||||||
notify_email: "noreply@example.com",
|
notify_email: "noreply@example.com",
|
||||||
skip_thread_containment: false,
|
skip_thread_containment: false
|
||||||
federating: false,
|
|
||||||
external_user_synchronization: false,
|
|
||||||
static_dir: "test/instance_static/"
|
|
||||||
|
|
||||||
config :pleroma, :activitypub, sign_object_fetches: false, follow_handshake_timeout: 0
|
|
||||||
|
|
||||||
# Configure your database
|
# Configure your database
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
|
@ -47,14 +37,10 @@
|
||||||
password: "postgres",
|
password: "postgres",
|
||||||
database: "pleroma_test",
|
database: "pleroma_test",
|
||||||
hostname: System.get_env("DB_HOST") || "localhost",
|
hostname: System.get_env("DB_HOST") || "localhost",
|
||||||
port: System.get_env("DB_PORT") || "5432",
|
pool: Ecto.Adapters.SQL.Sandbox
|
||||||
pool: Ecto.Adapters.SQL.Sandbox,
|
|
||||||
pool_size: 50
|
|
||||||
|
|
||||||
config :pleroma, :dangerzone, override_repo_pool_size: true
|
|
||||||
|
|
||||||
# Reduce hash rounds for testing
|
# Reduce hash rounds for testing
|
||||||
config :pleroma, :password, iterations: 1
|
config :pbkdf2_elixir, rounds: 1
|
||||||
|
|
||||||
config :tesla, adapter: Tesla.Mock
|
config :tesla, adapter: Tesla.Mock
|
||||||
|
|
||||||
|
@ -63,33 +49,22 @@
|
||||||
ignore_hosts: [],
|
ignore_hosts: [],
|
||||||
ignore_tld: ["local", "localdomain", "lan"]
|
ignore_tld: ["local", "localdomain", "lan"]
|
||||||
|
|
||||||
config :pleroma, :instance,
|
|
||||||
multi_factor_authentication: [
|
|
||||||
totp: [
|
|
||||||
# digits 6 or 8
|
|
||||||
digits: 6,
|
|
||||||
period: 30
|
|
||||||
],
|
|
||||||
backup_codes: [
|
|
||||||
number: 2,
|
|
||||||
length: 6
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
config :web_push_encryption, :vapid_details,
|
config :web_push_encryption, :vapid_details,
|
||||||
subject: "mailto:administrator@example.com",
|
subject: "mailto:administrator@example.com",
|
||||||
public_key:
|
public_key:
|
||||||
"BLH1qVhJItRGCfxgTtONfsOKDc9VRAraXw-3NsmjMngWSh7NxOizN6bkuRA7iLTMPS82PjwJAr3UoK9EC1IFrz4",
|
"BLH1qVhJItRGCfxgTtONfsOKDc9VRAraXw-3NsmjMngWSh7NxOizN6bkuRA7iLTMPS82PjwJAr3UoK9EC1IFrz4",
|
||||||
private_key: "_-XZ0iebPrRfZ_o0-IatTdszYa8VCH1yLN-JauK7HHA"
|
private_key: "_-XZ0iebPrRfZ_o0-IatTdszYa8VCH1yLN-JauK7HHA"
|
||||||
|
|
||||||
config :pleroma, Oban, testing: :manual
|
config :web_push_encryption, :http_client, Pleroma.Web.WebPushHttpClientMock
|
||||||
|
|
||||||
|
config :pleroma_job_queue, disabled: true
|
||||||
|
|
||||||
config :pleroma, Pleroma.ScheduledActivity,
|
config :pleroma, Pleroma.ScheduledActivity,
|
||||||
daily_user_limit: 2,
|
daily_user_limit: 2,
|
||||||
total_user_limit: 3,
|
total_user_limit: 3,
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
config :pleroma, :rate_limit, %{}
|
config :pleroma, :rate_limit, app_account_creation: {10_000, 5}
|
||||||
|
|
||||||
config :pleroma, :http_security, report_uri: "https://endpoint.com"
|
config :pleroma, :http_security, report_uri: "https://endpoint.com"
|
||||||
|
|
||||||
|
@ -99,47 +74,10 @@
|
||||||
config :pleroma, :database, rum_enabled: rum_enabled
|
config :pleroma, :database, rum_enabled: rum_enabled
|
||||||
IO.puts("RUM enabled: #{rum_enabled}")
|
IO.puts("RUM enabled: #{rum_enabled}")
|
||||||
|
|
||||||
config :joken, default_signer: "yU8uHKq+yyAkZ11Hx//jcdacWc8yQ1bxAAGrplzB0Zwwjkp35v0RK9SO8WTPr6QZ"
|
try do
|
||||||
|
|
||||||
config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
|
|
||||||
|
|
||||||
config :pleroma, :modules, runtime_dir: "test/fixtures/modules"
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Gun, Pleroma.GunMock
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: true
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Plugs.RemoteIp, enabled: false
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: true
|
|
||||||
|
|
||||||
config :tzdata, :autoupdate, :disabled
|
|
||||||
|
|
||||||
config :pleroma, :mrf, policies: []
|
|
||||||
|
|
||||||
config :pleroma, :pipeline,
|
|
||||||
object_validator: Pleroma.Web.ActivityPub.ObjectValidatorMock,
|
|
||||||
mrf: Pleroma.Web.ActivityPub.MRFMock,
|
|
||||||
activity_pub: Pleroma.Web.ActivityPub.ActivityPubMock,
|
|
||||||
side_effects: Pleroma.Web.ActivityPub.SideEffectsMock,
|
|
||||||
federator: Pleroma.Web.FederatorMock,
|
|
||||||
config: Pleroma.ConfigMock
|
|
||||||
|
|
||||||
config :pleroma, :cachex, provider: Pleroma.CachexMock
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.WebFinger, update_nickname_on_user_fetch: false
|
|
||||||
|
|
||||||
config :pleroma, :side_effects,
|
|
||||||
ap_streamer: Pleroma.Web.ActivityPub.ActivityPubMock,
|
|
||||||
logger: Pleroma.LoggerMock
|
|
||||||
|
|
||||||
# Reduce recompilation time
|
|
||||||
# https://dashbit.co/blog/speeding-up-re-compilation-of-elixir-projects
|
|
||||||
config :phoenix, :plug_init_mode, :runtime
|
|
||||||
|
|
||||||
if File.exists?("./config/test.secret.exs") do
|
|
||||||
import_config "test.secret.exs"
|
import_config "test.secret.exs"
|
||||||
else
|
rescue
|
||||||
|
_ ->
|
||||||
IO.puts(
|
IO.puts(
|
||||||
"You may want to create test.secret.exs to declare custom database connection parameters."
|
"You may want to create test.secret.exs to declare custom database connection parameters."
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"skip_files": [
|
|
||||||
"test/support",
|
|
||||||
"lib/mix/tasks/pleroma/benchmark.ex",
|
|
||||||
"lib/credo/check/consistency/file_location.ex"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/ash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "-- Waiting for database..."
|
|
||||||
while ! pg_isready -U ${DB_USER:-pleroma} -d postgres://${DB_HOST:-db}:${DB_PORT:-5432}/${DB_NAME:-pleroma} -t 1; do
|
|
||||||
sleep 1s
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "-- Running migrations..."
|
|
||||||
$HOME/bin/pleroma_ctl migrate
|
|
||||||
|
|
||||||
echo "-- Starting!"
|
|
||||||
exec $HOME/bin/pleroma start
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Backup/Restore your instance
|
||||||
|
|
||||||
|
## Backup
|
||||||
|
|
||||||
|
1. Stop the Pleroma service.
|
||||||
|
2. Go to the working directory of Pleroma (default is `/opt/pleroma`)
|
||||||
|
3. Run `sudo -Hu postgres pg_dump -d <pleroma_db> --format=custom -f </path/to/backup_location/pleroma.pgdump>`
|
||||||
|
4. Copy `pleroma.pgdump`, `config/prod.secret.exs` and the `uploads` folder to your backup destination. If you have other modifications, copy those changes too.
|
||||||
|
5. Restart the Pleroma service.
|
||||||
|
|
||||||
|
## Restore
|
||||||
|
|
||||||
|
1. Stop the Pleroma service.
|
||||||
|
2. Go to the working directory of Pleroma (default is `/opt/pleroma`)
|
||||||
|
3. Copy the above mentioned files back to their original position.
|
||||||
|
4. Run `sudo -Hu postgres pg_restore -d <pleroma_db> -v -1 </path/to/backup_location/pleroma.pgdump>`
|
||||||
|
5. Restart the Pleroma service.
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Updating your instance
|
||||||
|
1. Go to the working directory of Pleroma (default is `/opt/pleroma`)
|
||||||
|
2. Run `git pull`. This pulls the latest changes from upstream.
|
||||||
|
3. Run `mix deps.get`. This pulls in any new dependencies.
|
||||||
|
4. Stop the Pleroma service.
|
||||||
|
5. Run `mix ecto.migrate`[^1]. This task performs database migrations, if there were any.
|
||||||
|
6. Start the Pleroma service.
|
||||||
|
|
||||||
|
[^1]: Prefix with `MIX_ENV=prod` to run it using the production config file.
|
|
@ -1,157 +0,0 @@
|
||||||
# Transfering the config to/from the database
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Transfer config from file to DB.
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
You need to add the following to your config before executing this command:
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, configurable_from_database: true
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config migrate_to_db
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.config migrate_to_db
|
|
||||||
```
|
|
||||||
|
|
||||||
## Transfer config from DB to `config/env.exported_from_db.secret.exs`
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
In-Database configuration will still be applied after executing this command unless you set the following in your config:
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, configurable_from_database: false
|
|
||||||
```
|
|
||||||
|
|
||||||
Options:
|
|
||||||
|
|
||||||
- `<path>` - where to save migrated config. E.g. `--path=/tmp`. If file saved into non standart folder, you must manually copy file into directory where Pleroma can read it. For OTP install path will be `PLEROMA_CONFIG_PATH` or `/etc/pleroma`. For installation from source - `config` directory in the pleroma folder.
|
|
||||||
- `<env>` - environment, for which is migrated config. By default is `prod`.
|
|
||||||
- To delete transferred settings from database optional flag `-d` can be used
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config migrate_from_db [--env=<env>] [-d] [--path=<path>]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
```sh
|
|
||||||
mix pleroma.config migrate_from_db [--env=<env>] [-d] [--path=<path>]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dump all of the config settings defined in the database
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config dump
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.config dump
|
|
||||||
```
|
|
||||||
|
|
||||||
## List individual configuration groups in the database
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config groups
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.config groups
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dump the saved configuration values for a specific group or key
|
|
||||||
|
|
||||||
e.g., this shows all the settings under `config :pleroma`
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config dump pleroma
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.config dump pleroma
|
|
||||||
```
|
|
||||||
|
|
||||||
To get values under a specific key:
|
|
||||||
|
|
||||||
e.g., this shows all the settings under `config :pleroma, :instance`
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config dump pleroma instance
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.config dump pleroma instance
|
|
||||||
```
|
|
||||||
|
|
||||||
## Delete the saved configuration values for a specific group or key
|
|
||||||
|
|
||||||
e.g., this deletes all the settings under `config :tesla`
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config delete [--force] tesla
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.config delete [--force] tesla
|
|
||||||
```
|
|
||||||
|
|
||||||
To delete values under a specific key:
|
|
||||||
|
|
||||||
e.g., this deletes all the settings under `config :phoenix, :stacktrace_depth`
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config delete [--force] phoenix stacktrace_depth
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.config delete [--force] phoenix stacktrace_depth
|
|
||||||
```
|
|
||||||
|
|
||||||
## Remove all settings from the database
|
|
||||||
|
|
||||||
This forcibly removes all saved values in the database.
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl config [--force] reset
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.config [--force] reset
|
|
||||||
```
|
|
|
@ -1,161 +0,0 @@
|
||||||
# Database maintenance tasks
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
!!! danger
|
|
||||||
These mix tasks can take a long time to complete. Many of them were written to address specific database issues that happened because of bugs in migrations or other specific scenarios. Do not run these tasks "just in case" if everything is fine your instance.
|
|
||||||
|
|
||||||
## Replace embedded objects with their references
|
|
||||||
|
|
||||||
Replaces embedded objects with references to them in the `objects` table. Only needs to be ran once if the instance was created before Pleroma 1.0.5. The reason why this is not a migration is because it could significantly increase the database size after being ran, however after this `VACUUM FULL` will be able to reclaim about 20% (really depends on what is in the database, your mileage may vary) of the db size before the migration.
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database remove_embedded_objects [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database remove_embedded_objects [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Options
|
|
||||||
- `--vacuum` - run `VACUUM FULL` after the embedded objects are replaced with their references
|
|
||||||
|
|
||||||
## Prune old remote posts from the database
|
|
||||||
|
|
||||||
This will prune remote posts older than 90 days (configurable with [`config :pleroma, :instance, remote_post_retention_days`](../../configuration/cheatsheet.md#instance)) from the database, they will be refetched from source when accessed.
|
|
||||||
|
|
||||||
!!! danger
|
|
||||||
The disk space will only be reclaimed after `VACUUM FULL`. You may run out of disk space during the execution of the task or vacuuming if you don't have about 1/3rds of the database size free.
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database prune_objects [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database prune_objects [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
- `--vacuum` - run `VACUUM FULL` after the objects are pruned
|
|
||||||
|
|
||||||
## Create a conversation for all existing DMs
|
|
||||||
|
|
||||||
Can be safely re-run
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database bump_all_conversations
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database bump_all_conversations
|
|
||||||
```
|
|
||||||
|
|
||||||
## Remove duplicated items from following and update followers count for all users
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database update_users_following_followers_counts
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database update_users_following_followers_counts
|
|
||||||
```
|
|
||||||
|
|
||||||
## Fix the pre-existing "likes" collections for all objects
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database fix_likes_collections
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database fix_likes_collections
|
|
||||||
```
|
|
||||||
|
|
||||||
## Vacuum the database
|
|
||||||
|
|
||||||
### Analyze
|
|
||||||
|
|
||||||
Running an `analyze` vacuum job can improve performance by updating statistics used by the query planner. **It is safe to cancel this.**
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database vacuum analyze
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database vacuum analyze
|
|
||||||
```
|
|
||||||
|
|
||||||
### Full
|
|
||||||
|
|
||||||
Running a `full` vacuum job rebuilds your entire database by reading all of the data and rewriting it into smaller
|
|
||||||
and more compact files with an optimized layout. This process will take a long time and use additional disk space as
|
|
||||||
it builds the files side-by-side the existing database files. It can make your database faster and use less disk space,
|
|
||||||
but should only be run if necessary. **It is safe to cancel this.**
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database vacuum full
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database vacuum full
|
|
||||||
```
|
|
||||||
|
|
||||||
## Add expiration to all local statuses
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database ensure_expiration
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database ensure_expiration
|
|
||||||
```
|
|
||||||
|
|
||||||
## Change Text Search Configuration
|
|
||||||
|
|
||||||
Change `default_text_search_config` for database and (if necessary) text_search_config used in index, then rebuild index (it may take time).
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database set_text_search_config english
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database set_text_search_config english
|
|
||||||
```
|
|
||||||
|
|
||||||
See [PostgreSQL documentation](https://www.postgresql.org/docs/current/textsearch-configuration.html) and `docs/configuration/howto_search_cjk.md` for more detail.
|
|
|
@ -1,33 +0,0 @@
|
||||||
# Managing digest emails
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Send digest email since given date (user registration date by default) ignoring user activity status.
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl digest test <nickname> [since_date]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.digest test <nickname> [since_date]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl digest test donaldtheduck 2019-05-20
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.digest test donaldtheduck 2019-05-20
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
# EMail administration tasks
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Send test email (instance email by default)
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl email test [--to <destination email address>]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.email test [--to <destination email address>]
|
|
||||||
```
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl email test --to root@example.org
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.email test --to root@example.org
|
|
||||||
```
|
|
||||||
|
|
||||||
## Send confirmation emails to all unconfirmed user accounts
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl email resend_confirmation_emails
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.email resend_confirmation_emails
|
|
||||||
```
|
|
|
@ -1,61 +0,0 @@
|
||||||
# Managing emoji packs
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Lists emoji packs and metadata specified in the manifest
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl emoji ls-packs [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
```sh
|
|
||||||
mix pleroma.emoji ls-packs [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Options
|
|
||||||
- `-m, --manifest PATH/URL` - path to a custom manifest, it can either be an URL starting with `http`, in that case the manifest will be fetched from that address, or a local path
|
|
||||||
|
|
||||||
## Fetch, verify and install the specified packs from the manifest into `STATIC-DIR/emoji/PACK-NAME`
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl emoji get-packs [option ...] <pack ...>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
```sh
|
|
||||||
mix pleroma.emoji get-packs [option ...] <pack ...>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
- `-m, --manifest PATH/URL` - same as [`ls-packs`](#ls-packs)
|
|
||||||
|
|
||||||
## Create a new manifest entry and a file list from the specified remote pack file
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl emoji gen-pack PACK-URL
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
```sh
|
|
||||||
mix pleroma.emoji gen-pack PACK-URL
|
|
||||||
```
|
|
||||||
|
|
||||||
Currently, only .zip archives are recognized as remote pack files and packs are therefore assumed to be zip archives. This command is intended to run interactively and will first ask you some basic questions about the pack, then download the remote file and generate an SHA256 checksum for it, then generate an emoji file list for you.
|
|
||||||
|
|
||||||
The manifest entry will either be written to a newly created `pack_name.json` file (pack name is asked in questions) or appended to the existing one, *replacing* the old pack with the same name if it was in the file previously.
|
|
||||||
|
|
||||||
The file list will be written to the file specified previously, *replacing* that file. You _should_ check that the file list doesn't contain anything you don't need in the pack, that is, anything that is not an emoji (the whole pack is downloaded, but only emoji files are extracted).
|
|
||||||
|
|
||||||
## Reload emoji packs
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl emoji reload
|
|
||||||
```
|
|
||||||
|
|
||||||
This command only works with OTP releases.
|
|
|
@ -1,96 +0,0 @@
|
||||||
# Managing frontends
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl frontend install <frontend> [--ref <ref>] [--file <file>] [--build-url <build-url>] [--path <path>] [--build-dir <build-dir>]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.frontend install <frontend> [--ref <ref>] [--file <file>] [--build-url <build-url>] [--path <path>] [--build-dir <build-dir>]
|
|
||||||
```
|
|
||||||
|
|
||||||
Frontend can be installed either from local zip file, or automatically downloaded from the web.
|
|
||||||
|
|
||||||
You can give all the options directly on the command line, but missing information will be filled out by looking at the data configured under `frontends.available` in the config files.
|
|
||||||
|
|
||||||
Currently, known `<frontend>` values are:
|
|
||||||
|
|
||||||
- [admin-fe](https://git.pleroma.social/pleroma/admin-fe)
|
|
||||||
- [kenoma](http://git.pleroma.social/lambadalambda/kenoma)
|
|
||||||
- [pleroma-fe](http://git.pleroma.social/pleroma/pleroma-fe)
|
|
||||||
- [fedi-fe](https://git.pleroma.social/pleroma/fedi-fe)
|
|
||||||
- [soapbox](https://gitlab.com/soapbox-pub/soapbox)
|
|
||||||
|
|
||||||
You can still install frontends that are not configured, see below.
|
|
||||||
|
|
||||||
## Example installations for a known frontend
|
|
||||||
|
|
||||||
For a frontend configured under the `available` key, it's enough to install it by name.
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl frontend install pleroma
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.frontend install pleroma
|
|
||||||
```
|
|
||||||
|
|
||||||
This will download the latest build for the pre-configured `ref` and install it. It can then be configured as the one of the served frontends in the config file (see `primary` or `admin`).
|
|
||||||
|
|
||||||
You can override any of the details. To install a pleroma build from a different URL, you could do this:
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl frontend install pleroma --ref 2hu_edition --build-url https://example.org/raymoo.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.frontend install pleroma --ref 2hu_edition --build-url https://example.org/raymoo.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
Similarly, you can also install from a local zip file.
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl frontend install pleroma --ref mybuild --file ~/Downloads/doomfe.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.frontend install pleroma --ref mybuild --file ~/Downloads/doomfe.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
The resulting frontend will always be installed into a folder of this template: `${instance_static}/frontends/${name}/${ref}`.
|
|
||||||
|
|
||||||
Careful: This folder will be completely replaced on installation.
|
|
||||||
|
|
||||||
## Example installation for an unknown frontend
|
|
||||||
|
|
||||||
The installation process is the same, but you will have to give all the needed options on the command line. For example:
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl frontend install gensokyo --ref master --build-url https://gensokyo.2hu/builds/marisa.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.frontend install gensokyo --ref master --build-url https://gensokyo.2hu/builds/marisa.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
If you don't have a zip file but just want to install a frontend from a local path, you can simply copy the files over a folder of this template: `${instance_static}/frontends/${name}/${ref}`.
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
Every command should be ran as the `pleroma` user from it's home directory. For example if you are superuser, you would have to wrap the command in `su pleroma -s $SHELL -lc "$COMMAND"`.
|
|
||||||
|
|
||||||
??? note "From source note about `MIX_ENV`"
|
|
||||||
|
|
||||||
The `mix` command should be prefixed with the name of environment your Pleroma server is running in, usually it's `MIX_ENV=prod`
|
|
|
@ -1,45 +0,0 @@
|
||||||
# Managing instance configuration
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Generate a new configuration file
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl instance gen [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.instance gen [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
If any of the 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 <email>` - the email address of the instance admin
|
|
||||||
- `--notify-email <email>` - email address for notifications
|
|
||||||
- `--dbhost <hostname>` - the hostname of the PostgreSQL database to use
|
|
||||||
- `--dbname <database_name>` - the name of the database to use
|
|
||||||
- `--dbuser <username>` - the user (aka role) to use for the database connection
|
|
||||||
- `--dbpass <password>` - the password to use for the database connection
|
|
||||||
- `--rum <Y|N>` - Whether to enable RUM indexes
|
|
||||||
- `--indexable <Y|N>` - Allow/disallow indexing site by search engines
|
|
||||||
- `--db-configurable <Y|N>` - Allow/disallow configuring instance from admin part
|
|
||||||
- `--uploads-dir <path>` - the directory uploads go in when using a local uploader
|
|
||||||
- `--static-dir <path>` - the directory custom public files should be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)
|
|
||||||
- `--listen-ip <ip>` - the ip the app should listen to, defaults to 127.0.0.1
|
|
||||||
- `--listen-port <port>` - the port the app should listen to, defaults to 4000
|
|
||||||
- `--strip-uploads-location <Y|N>` - use ExifTool to strip uploads of sensitive location data
|
|
||||||
- `--read-uploads-description <Y|N>` - use ExifTool to read image descriptions from uploads
|
|
||||||
- `--anonymize-uploads <Y|N>` - randomize uploaded filenames
|
|
||||||
- `--dedupe-uploads <Y|N>` - store files based on their hash to reduce data storage requirements if duplicates are uploaded with different filenames
|
|
||||||
- `--skip-release-env` - skip generation the release environment file
|
|
||||||
- `--release-env-file` - release environment file path
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Creating trusted OAuth App
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Create trusted OAuth App.
|
|
||||||
|
|
||||||
Optional params:
|
|
||||||
* `-s SCOPES` - scopes for app, e.g. `read,write,follow,push`.
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl app create -n APP_NAME -r REDIRECT_URI
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.app create -n APP_NAME -r REDIRECT_URI
|
|
||||||
```
|
|
|
@ -1,45 +0,0 @@
|
||||||
# Managing relays
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Follow a relay
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl relay follow <relay_url>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.relay follow <relay_url>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Unfollow a remote relay
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl relay unfollow <relay_url>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.relay unfollow <relay_url>
|
|
||||||
```
|
|
||||||
|
|
||||||
## List relay subscriptions
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl relay list
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.relay list
|
|
||||||
```
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Managing robots.txt
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Generate a new robots.txt file and add it to the static directory
|
|
||||||
|
|
||||||
The `robots.txt` that ships by default is permissive. It allows well-behaved search engines to index all of your instance's URIs.
|
|
||||||
|
|
||||||
If you want to generate a restrictive `robots.txt`, you can run the following mix task. The generated `robots.txt` will be written in your instance [static directory](../../../configuration/static_dir/).
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl robots_txt disallow_all
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.robots_txt disallow_all
|
|
||||||
```
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Managing uploads
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Migrate uploads from local to remote storage
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl uploads migrate_local <target_uploader> [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.uploads migrate_local <target_uploader> [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
- `--delete` - delete local uploads after migrating them to the target uploader
|
|
||||||
|
|
||||||
A list of available uploaders can be seen in [Configuration Cheat Sheet](../../configuration/cheatsheet.md#pleromaupload)
|
|
|
@ -1,302 +0,0 @@
|
||||||
# Managing users
|
|
||||||
|
|
||||||
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
|
|
||||||
|
|
||||||
## Create a user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user new <nickname> <email> [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user new <nickname> <email> [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Options
|
|
||||||
- `--name <name>` - the user's display name
|
|
||||||
- `--bio <bio>` - the user's bio
|
|
||||||
- `--password <password>` - the user's password
|
|
||||||
- `--moderator`/`--no-moderator` - whether the user should be a moderator
|
|
||||||
- `--admin`/`--no-admin` - whether the user should be an admin
|
|
||||||
- `-y`, `--assume-yes`/`--no-assume-yes` - whether to assume yes to all questions
|
|
||||||
|
|
||||||
## List local users
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user list
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user list
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Generate an invite link
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user invite [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user invite [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### Options
|
|
||||||
- `--expires-at DATE` - last day on which token is active (e.g. "2019-04-05")
|
|
||||||
- `--max-use NUMBER` - maximum numbers of token uses
|
|
||||||
|
|
||||||
## List generated invites
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user invites
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user invites
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Revoke invite
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user revoke_invite <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user revoke_invite <token>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Delete a user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user rm <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user rm <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Delete user's posts and interactions
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user delete_activities <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user delete_activities <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Sign user out from all applications (delete user's OAuth tokens and authorizations)
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user sign_out <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user sign_out <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Activate a user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user activate NICKNAME
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user activate NICKNAME
|
|
||||||
```
|
|
||||||
|
|
||||||
## Deactivate a user and unsubscribes local users from the user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user deactivate NICKNAME
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user deactivate NICKNAME
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Deactivate all accounts from an instance and unsubscribe local users on it
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user deactivate_all_from_instance <instance>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user deactivate_all_from_instance <instance>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Create a password reset link for user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user reset_password <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user reset_password <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Disable Multi Factor Authentication (MFA/2FA) for a user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user reset_mfa <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user reset_mfa <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Set the value of the given user's settings
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user set <nickname> [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user set <nickname> [option ...]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
- `--admin`/`--no-admin` - whether the user should be an admin
|
|
||||||
- `--confirmed`/`--no-confirmed` - whether the user account is confirmed
|
|
||||||
- `--locked`/`--no-locked` - whether the user should be locked
|
|
||||||
- `--moderator`/`--no-moderator` - whether the user should be a moderator
|
|
||||||
|
|
||||||
## Add tags to a user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user tag <nickname> <tags>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user tag <nickname> <tags>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Delete tags from a user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user untag <nickname> <tags>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user untag <nickname> <tags>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Toggle confirmation status of the user
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user confirm <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user confirm <nickname>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Set confirmation status for all regular active users
|
|
||||||
*Admins and moderators are excluded*
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user confirm_all
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user confirm_all
|
|
||||||
```
|
|
||||||
|
|
||||||
## Revoke confirmation status for all regular active users
|
|
||||||
*Admins and moderators are excluded*
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl user unconfirm_all
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.user unconfirm_all
|
|
||||||
```
|
|
|
@ -1,41 +0,0 @@
|
||||||
# Backup/Restore/Move/Remove your instance
|
|
||||||
|
|
||||||
## Backup
|
|
||||||
|
|
||||||
1. Stop the Pleroma service.
|
|
||||||
2. Go to the working directory of Pleroma (default is `/opt/pleroma`)
|
|
||||||
3. Run `sudo -Hu postgres pg_dump -d <pleroma_db> --format=custom -f </path/to/backup_location/pleroma.pgdump>` (make sure the postgres user has write access to the destination file)
|
|
||||||
4. Copy `pleroma.pgdump`, `config/prod.secret.exs`, `config/setup_db.psql` (if still available) and the `uploads` folder to your backup destination. If you have other modifications, copy those changes too.
|
|
||||||
5. Restart the Pleroma service.
|
|
||||||
|
|
||||||
## Restore/Move
|
|
||||||
|
|
||||||
1. Optionally reinstall Pleroma (either on the same server or on another server if you want to move servers).
|
|
||||||
2. Stop the Pleroma service.
|
|
||||||
3. Go to the working directory of Pleroma (default is `/opt/pleroma`)
|
|
||||||
4. Copy the above mentioned files back to their original position.
|
|
||||||
5. Drop the existing database and user if restoring in-place. `sudo -Hu postgres psql -c 'DROP DATABASE <pleroma_db>;';` `sudo -Hu postgres psql -c 'DROP USER <pleroma_db>;'`
|
|
||||||
6. Restore the database schema and pleroma postgres role the with the original `setup_db.psql` if you have it: `sudo -Hu postgres psql -f config/setup_db.psql`.
|
|
||||||
|
|
||||||
Alternatively, run the `mix pleroma.instance gen` task again. You can ignore most of the questions, but make the database user, name, and password the same as found in your backup of `config/prod.secret.exs`. Then run the restoration of the pleroma role and schema with of the generated `config/setup_db.psql` as instructed above. You may delete the `config/generated_config.exs` file as it is not needed.
|
|
||||||
|
|
||||||
7. Now restore the Pleroma instance's data into the empty database schema: `sudo -Hu postgres pg_restore -d <pleroma_db> -v -1 </path/to/backup_location/pleroma.pgdump>`
|
|
||||||
8. If you installed a newer Pleroma version, you should run `mix ecto.migrate`[^1]. This task performs database migrations, if there were any.
|
|
||||||
9. Restart the Pleroma service.
|
|
||||||
10. Run `sudo -Hu postgres vacuumdb --all --analyze-in-stages`. This will quickly generate the statistics so that postgres can properly plan queries.
|
|
||||||
11. If setting up on a new server configure Nginx by using the `installation/pleroma.nginx` config sample or reference the Pleroma installation guide for your OS which contains the Nginx configuration instructions.
|
|
||||||
|
|
||||||
[^1]: Prefix with `MIX_ENV=prod` to run it using the production config file.
|
|
||||||
|
|
||||||
## Remove
|
|
||||||
|
|
||||||
1. Optionally you can remove the users of your instance. This will trigger delete requests for their accounts and posts. Note that this is 'best effort' and doesn't mean that all traces of your instance will be gone from the fediverse.
|
|
||||||
* You can do this from the admin-FE where you can select all local users and delete the accounts using the *Moderate multiple users* dropdown.
|
|
||||||
* You can also list local users and delete them individualy using the CLI tasks for [Managing users](./CLI_tasks/user.md).
|
|
||||||
2. Stop the Pleroma service `systemctl stop pleroma`
|
|
||||||
3. Disable pleroma from systemd `systemctl disable pleroma`
|
|
||||||
4. Remove the files and folders you created during installation (see installation guide). This includes the pleroma, nginx and systemd files and folders.
|
|
||||||
5. Reload nginx now that the configuration is removed `systemctl reload nginx`
|
|
||||||
6. Remove the database and database user `sudo -Hu postgres psql -c 'DROP DATABASE <pleroma_db>;';` `sudo -Hu postgres psql -c 'DROP USER <pleroma_db>;'`
|
|
||||||
7. Remove the system user `userdel pleroma`
|
|
||||||
8. Remove the dependencies that you don't need anymore (see installation guide). Make sure you don't remove packages that are still needed for other software that you have running!
|
|
|
@ -1,27 +0,0 @@
|
||||||
# Updating your instance
|
|
||||||
|
|
||||||
You should **always check the [release notes/changelog](https://git.pleroma.social/pleroma/pleroma/-/releases)** in case there are config deprecations, special update steps, etc.
|
|
||||||
|
|
||||||
Besides that, doing the following is generally enough:
|
|
||||||
|
|
||||||
## For OTP installations
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# Download the new release
|
|
||||||
su pleroma -s $SHELL -lc "./bin/pleroma_ctl update"
|
|
||||||
|
|
||||||
# Migrate the database, you are advised to stop the instance before doing that
|
|
||||||
su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate"
|
|
||||||
```
|
|
||||||
|
|
||||||
## For from source installations (using git)
|
|
||||||
|
|
||||||
1. Go to the working directory of Pleroma (default is `/opt/pleroma`)
|
|
||||||
2. Run `git checkout <tagged release>` [^1]. e.g. `git checkout v2.4.5` This pulls the [tagged release](https://git.pleroma.social/pleroma/pleroma/-/releases) from upstream.
|
|
||||||
3. Run `mix deps.get` [^1]. This pulls in any new dependencies.
|
|
||||||
4. Stop the Pleroma service.
|
|
||||||
5. Run `mix ecto.migrate` [^1] [^2]. This task performs database migrations, if there were any.
|
|
||||||
6. Start the Pleroma service.
|
|
||||||
|
|
||||||
[^1]: Depending on which install guide you followed (for example on Debian/Ubuntu), you want to run `git` and `mix` tasks as `pleroma` user by adding `sudo -Hu pleroma` before the command.
|
|
||||||
[^2]: Prefix with `MIX_ENV=prod` to run it using the production config file.
|
|
|
@ -0,0 +1,648 @@
|
||||||
|
# Admin API
|
||||||
|
|
||||||
|
Authentication is required and the user must be an admin.
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users`
|
||||||
|
|
||||||
|
### List users
|
||||||
|
|
||||||
|
- Method `GET`
|
||||||
|
- Query Params:
|
||||||
|
- *optional* `query`: **string** search term (e.g. nickname, domain, nickname@domain)
|
||||||
|
- *optional* `filters`: **string** comma-separated string of filters:
|
||||||
|
- `local`: only local users
|
||||||
|
- `external`: only external users
|
||||||
|
- `active`: only active users
|
||||||
|
- `deactivated`: only deactivated users
|
||||||
|
- `is_admin`: users with admin role
|
||||||
|
- `is_moderator`: users with moderator role
|
||||||
|
- *optional* `page`: **integer** page number
|
||||||
|
- *optional* `page_size`: **integer** number of users per page (default is `50`)
|
||||||
|
- *optional* `tags`: **[string]** tags list
|
||||||
|
- *optional* `name`: **string** user display name
|
||||||
|
- *optional* `email`: **string** user email
|
||||||
|
- Example: `https://mypleroma.org/api/pleroma/admin/users?query=john&filters=local,active&page=1&page_size=10&tags[]=some_tag&tags[]=another_tag&name=display_name&email=email@example.com`
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"page_size": integer,
|
||||||
|
"count": integer,
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"deactivated": bool,
|
||||||
|
"id": integer,
|
||||||
|
"nickname": string,
|
||||||
|
"roles": {
|
||||||
|
"admin": bool,
|
||||||
|
"moderator": bool
|
||||||
|
},
|
||||||
|
"local": bool,
|
||||||
|
"tags": array
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users`
|
||||||
|
|
||||||
|
### Remove a user
|
||||||
|
|
||||||
|
- Method `DELETE`
|
||||||
|
- Params:
|
||||||
|
- `nickname`
|
||||||
|
- Response: User’s nickname
|
||||||
|
|
||||||
|
### Create a user
|
||||||
|
|
||||||
|
- Method: `POST`
|
||||||
|
- Params:
|
||||||
|
- `nickname`
|
||||||
|
- `email`
|
||||||
|
- `password`
|
||||||
|
- Response: User’s nickname
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/follow`
|
||||||
|
### Make a user follow another user
|
||||||
|
|
||||||
|
- Methods: `POST`
|
||||||
|
- Params:
|
||||||
|
- `follower`: The nickname of the follower
|
||||||
|
- `followed`: The nickname of the followed
|
||||||
|
- Response:
|
||||||
|
- "ok"
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/unfollow`
|
||||||
|
### Make a user unfollow another user
|
||||||
|
|
||||||
|
- Methods: `POST`
|
||||||
|
- Params:
|
||||||
|
- `follower`: The nickname of the follower
|
||||||
|
- `followed`: The nickname of the followed
|
||||||
|
- Response:
|
||||||
|
- "ok"
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/:nickname/toggle_activation`
|
||||||
|
|
||||||
|
### Toggle user activation
|
||||||
|
|
||||||
|
- Method: `PATCH`
|
||||||
|
- Params:
|
||||||
|
- `nickname`
|
||||||
|
- Response: User’s object
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"deactivated": bool,
|
||||||
|
"id": integer,
|
||||||
|
"nickname": string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/tag`
|
||||||
|
|
||||||
|
### Tag a list of users
|
||||||
|
|
||||||
|
- Method: `PUT`
|
||||||
|
- Params:
|
||||||
|
- `nicknames` (array)
|
||||||
|
- `tags` (array)
|
||||||
|
|
||||||
|
### Untag a list of users
|
||||||
|
|
||||||
|
- Method: `DELETE`
|
||||||
|
- Params:
|
||||||
|
- `nicknames` (array)
|
||||||
|
- `tags` (array)
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/:nickname/permission_group`
|
||||||
|
|
||||||
|
### Get user user permission groups membership
|
||||||
|
|
||||||
|
- Method: `GET`
|
||||||
|
- Params: none
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"is_moderator": bool,
|
||||||
|
"is_admin": bool
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/:nickname/permission_group/:permission_group`
|
||||||
|
|
||||||
|
Note: Available `:permission_group` is currently moderator and admin. 404 is returned when the permission group doesn’t exist.
|
||||||
|
|
||||||
|
### Get user user permission groups membership per permission group
|
||||||
|
|
||||||
|
- Method: `GET`
|
||||||
|
- Params: none
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"is_moderator": bool,
|
||||||
|
"is_admin": bool
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add user in permission group
|
||||||
|
|
||||||
|
- Method: `POST`
|
||||||
|
- Params: none
|
||||||
|
- Response:
|
||||||
|
- On failure: `{"error": "…"}`
|
||||||
|
- On success: JSON of the `user.info`
|
||||||
|
|
||||||
|
### Remove user from permission group
|
||||||
|
|
||||||
|
- Method: `DELETE`
|
||||||
|
- Params: none
|
||||||
|
- Response:
|
||||||
|
- On failure: `{"error": "…"}`
|
||||||
|
- On success: JSON of the `user.info`
|
||||||
|
- Note: An admin cannot revoke their own admin status.
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/:nickname/activation_status`
|
||||||
|
|
||||||
|
### Active or deactivate a user
|
||||||
|
|
||||||
|
- Method: `PUT`
|
||||||
|
- Params:
|
||||||
|
- `nickname`
|
||||||
|
- `status` BOOLEAN field, false value means deactivation.
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/:nickname`
|
||||||
|
|
||||||
|
### Retrive the details of a user
|
||||||
|
|
||||||
|
- Method: `GET`
|
||||||
|
- Params:
|
||||||
|
- `nickname`
|
||||||
|
- Response:
|
||||||
|
- On failure: `Not found`
|
||||||
|
- On success: JSON of the user
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/relay`
|
||||||
|
|
||||||
|
### Follow a Relay
|
||||||
|
|
||||||
|
- Methods: `POST`
|
||||||
|
- Params:
|
||||||
|
- `relay_url`
|
||||||
|
- Response:
|
||||||
|
- On success: URL of the followed relay
|
||||||
|
|
||||||
|
### Unfollow a Relay
|
||||||
|
|
||||||
|
- Methods: `DELETE`
|
||||||
|
- Params:
|
||||||
|
- `relay_url`
|
||||||
|
- Response:
|
||||||
|
- On success: URL of the unfollowed relay
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/invite_token`
|
||||||
|
|
||||||
|
### Get an account registration invite token
|
||||||
|
|
||||||
|
- Methods: `GET`
|
||||||
|
- Params:
|
||||||
|
- *optional* `invite` => [
|
||||||
|
- *optional* `max_use` (integer)
|
||||||
|
- *optional* `expires_at` (date string e.g. "2019-04-07")
|
||||||
|
]
|
||||||
|
- Response: invite token (base64 string)
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/invites`
|
||||||
|
|
||||||
|
### Get a list of generated invites
|
||||||
|
|
||||||
|
- Methods: `GET`
|
||||||
|
- Params: none
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
|
||||||
|
"invites": [
|
||||||
|
{
|
||||||
|
"id": integer,
|
||||||
|
"token": string,
|
||||||
|
"used": boolean,
|
||||||
|
"expires_at": date,
|
||||||
|
"uses": integer,
|
||||||
|
"max_use": integer,
|
||||||
|
"invite_type": string (possible values: `one_time`, `reusable`, `date_limited`, `reusable_date_limited`)
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/revoke_invite`
|
||||||
|
|
||||||
|
### Revoke invite by token
|
||||||
|
|
||||||
|
- Methods: `POST`
|
||||||
|
- Params:
|
||||||
|
- `token`
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": integer,
|
||||||
|
"token": string,
|
||||||
|
"used": boolean,
|
||||||
|
"expires_at": date,
|
||||||
|
"uses": integer,
|
||||||
|
"max_use": integer,
|
||||||
|
"invite_type": string (possible values: `one_time`, `reusable`, `date_limited`, `reusable_date_limited`)
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/email_invite`
|
||||||
|
|
||||||
|
### Sends registration invite via email
|
||||||
|
|
||||||
|
- Methods: `POST`
|
||||||
|
- Params:
|
||||||
|
- `email`
|
||||||
|
- `name`, optional
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/users/:nickname/password_reset`
|
||||||
|
|
||||||
|
### Get a password reset token for a given nickname
|
||||||
|
|
||||||
|
- Methods: `GET`
|
||||||
|
- Params: none
|
||||||
|
- Response: password reset token (base64 string)
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/reports`
|
||||||
|
### Get a list of reports
|
||||||
|
- Method `GET`
|
||||||
|
- Params:
|
||||||
|
- `state`: optional, the state of reports. Valid values are `open`, `closed` and `resolved`
|
||||||
|
- `limit`: optional, the number of records to retrieve
|
||||||
|
- `since_id`: optional, returns results that are more recent than the specified id
|
||||||
|
- `max_id`: optional, returns results that are older than the specified id
|
||||||
|
- Response:
|
||||||
|
- On failure: 403 Forbidden error `{"error": "error_msg"}` when requested by anonymous or non-admin
|
||||||
|
- On success: JSON, returns a list of reports, where:
|
||||||
|
- `account`: the user who has been reported
|
||||||
|
- `actor`: the user who has sent the report
|
||||||
|
- `statuses`: list of statuses that have been included to the report
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"reports": [
|
||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"acct": "user",
|
||||||
|
"avatar": "https://pleroma.example.org/images/avi.png",
|
||||||
|
"avatar_static": "https://pleroma.example.org/images/avi.png",
|
||||||
|
"bot": false,
|
||||||
|
"created_at": "2019-04-23T17:32:04.000Z",
|
||||||
|
"display_name": "User",
|
||||||
|
"emojis": [],
|
||||||
|
"fields": [],
|
||||||
|
"followers_count": 1,
|
||||||
|
"following_count": 1,
|
||||||
|
"header": "https://pleroma.example.org/images/banner.png",
|
||||||
|
"header_static": "https://pleroma.example.org/images/banner.png",
|
||||||
|
"id": "9i6dAJqSGSKMzLG2Lo",
|
||||||
|
"locked": false,
|
||||||
|
"note": "",
|
||||||
|
"pleroma": {
|
||||||
|
"confirmation_pending": false,
|
||||||
|
"hide_favorites": true,
|
||||||
|
"hide_followers": false,
|
||||||
|
"hide_follows": false,
|
||||||
|
"is_admin": false,
|
||||||
|
"is_moderator": false,
|
||||||
|
"relationship": {},
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"note": "",
|
||||||
|
"pleroma": {},
|
||||||
|
"sensitive": false
|
||||||
|
},
|
||||||
|
"statuses_count": 3,
|
||||||
|
"url": "https://pleroma.example.org/users/user",
|
||||||
|
"username": "user"
|
||||||
|
},
|
||||||
|
"actor": {
|
||||||
|
"acct": "lain",
|
||||||
|
"avatar": "https://pleroma.example.org/images/avi.png",
|
||||||
|
"avatar_static": "https://pleroma.example.org/images/avi.png",
|
||||||
|
"bot": false,
|
||||||
|
"created_at": "2019-03-28T17:36:03.000Z",
|
||||||
|
"display_name": "Roger Braun",
|
||||||
|
"emojis": [],
|
||||||
|
"fields": [],
|
||||||
|
"followers_count": 1,
|
||||||
|
"following_count": 1,
|
||||||
|
"header": "https://pleroma.example.org/images/banner.png",
|
||||||
|
"header_static": "https://pleroma.example.org/images/banner.png",
|
||||||
|
"id": "9hEkA5JsvAdlSrocam",
|
||||||
|
"locked": false,
|
||||||
|
"note": "",
|
||||||
|
"pleroma": {
|
||||||
|
"confirmation_pending": false,
|
||||||
|
"hide_favorites": false,
|
||||||
|
"hide_followers": false,
|
||||||
|
"hide_follows": false,
|
||||||
|
"is_admin": false,
|
||||||
|
"is_moderator": false,
|
||||||
|
"relationship": {},
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"note": "",
|
||||||
|
"pleroma": {},
|
||||||
|
"sensitive": false
|
||||||
|
},
|
||||||
|
"statuses_count": 1,
|
||||||
|
"url": "https://pleroma.example.org/users/lain",
|
||||||
|
"username": "lain"
|
||||||
|
},
|
||||||
|
"content": "Please delete it",
|
||||||
|
"created_at": "2019-04-29T19:48:15.000Z",
|
||||||
|
"id": "9iJGOv1j8hxuw19bcm",
|
||||||
|
"state": "open",
|
||||||
|
"statuses": [
|
||||||
|
{
|
||||||
|
"account": { ... },
|
||||||
|
"application": {
|
||||||
|
"name": "Web",
|
||||||
|
"website": null
|
||||||
|
},
|
||||||
|
"bookmarked": false,
|
||||||
|
"card": null,
|
||||||
|
"content": "<span class=\"h-card\"><a data-user=\"9hEkA5JsvAdlSrocam\" class=\"u-url mention\" href=\"https://pleroma.example.org/users/lain\">@<span>lain</span></a></span> click on my link <a href=\"https://www.google.com/\">https://www.google.com/</a>",
|
||||||
|
"created_at": "2019-04-23T19:15:47.000Z",
|
||||||
|
"emojis": [],
|
||||||
|
"favourited": false,
|
||||||
|
"favourites_count": 0,
|
||||||
|
"id": "9i6mQ9uVrrOmOime8m",
|
||||||
|
"in_reply_to_account_id": null,
|
||||||
|
"in_reply_to_id": null,
|
||||||
|
"language": null,
|
||||||
|
"media_attachments": [],
|
||||||
|
"mentions": [
|
||||||
|
{
|
||||||
|
"acct": "lain",
|
||||||
|
"id": "9hEkA5JsvAdlSrocam",
|
||||||
|
"url": "https://pleroma.example.org/users/lain",
|
||||||
|
"username": "lain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"acct": "user",
|
||||||
|
"id": "9i6dAJqSGSKMzLG2Lo",
|
||||||
|
"url": "https://pleroma.example.org/users/user",
|
||||||
|
"username": "user"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"muted": false,
|
||||||
|
"pinned": false,
|
||||||
|
"pleroma": {
|
||||||
|
"content": {
|
||||||
|
"text/plain": "@lain click on my link https://www.google.com/"
|
||||||
|
},
|
||||||
|
"conversation_id": 28,
|
||||||
|
"in_reply_to_account_acct": null,
|
||||||
|
"local": true,
|
||||||
|
"spoiler_text": {
|
||||||
|
"text/plain": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reblog": null,
|
||||||
|
"reblogged": false,
|
||||||
|
"reblogs_count": 0,
|
||||||
|
"replies_count": 0,
|
||||||
|
"sensitive": false,
|
||||||
|
"spoiler_text": "",
|
||||||
|
"tags": [],
|
||||||
|
"uri": "https://pleroma.example.org/objects/8717b90f-8e09-4b58-97b0-e3305472b396",
|
||||||
|
"url": "https://pleroma.example.org/notice/9i6mQ9uVrrOmOime8m",
|
||||||
|
"visibility": "direct"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/reports/:id`
|
||||||
|
### Get an individual report
|
||||||
|
- Method `GET`
|
||||||
|
- Params:
|
||||||
|
- `id`
|
||||||
|
- Response:
|
||||||
|
- On failure:
|
||||||
|
- 403 Forbidden `{"error": "error_msg"}`
|
||||||
|
- 404 Not Found `"Not found"`
|
||||||
|
- On success: JSON, Report object (see above)
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/reports/:id`
|
||||||
|
### Change the state of the report
|
||||||
|
- Method `PUT`
|
||||||
|
- Params:
|
||||||
|
- `id`
|
||||||
|
- `state`: required, the new state. Valid values are `open`, `closed` and `resolved`
|
||||||
|
- Response:
|
||||||
|
- On failure:
|
||||||
|
- 400 Bad Request `"Unsupported state"`
|
||||||
|
- 403 Forbidden `{"error": "error_msg"}`
|
||||||
|
- 404 Not Found `"Not found"`
|
||||||
|
- On success: JSON, Report object (see above)
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/reports/:id/respond`
|
||||||
|
### Respond to a report
|
||||||
|
- Method `POST`
|
||||||
|
- Params:
|
||||||
|
- `id`
|
||||||
|
- `status`: required, the message
|
||||||
|
- Response:
|
||||||
|
- On failure:
|
||||||
|
- 400 Bad Request `"Invalid parameters"` when `status` is missing
|
||||||
|
- 403 Forbidden `{"error": "error_msg"}`
|
||||||
|
- 404 Not Found `"Not found"`
|
||||||
|
- On success: JSON, created Mastodon Status entity
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"account": { ... },
|
||||||
|
"application": {
|
||||||
|
"name": "Web",
|
||||||
|
"website": null
|
||||||
|
},
|
||||||
|
"bookmarked": false,
|
||||||
|
"card": null,
|
||||||
|
"content": "Your claim is going to be closed",
|
||||||
|
"created_at": "2019-05-11T17:13:03.000Z",
|
||||||
|
"emojis": [],
|
||||||
|
"favourited": false,
|
||||||
|
"favourites_count": 0,
|
||||||
|
"id": "9ihuiSL1405I65TmEq",
|
||||||
|
"in_reply_to_account_id": null,
|
||||||
|
"in_reply_to_id": null,
|
||||||
|
"language": null,
|
||||||
|
"media_attachments": [],
|
||||||
|
"mentions": [
|
||||||
|
{
|
||||||
|
"acct": "user",
|
||||||
|
"id": "9i6dAJqSGSKMzLG2Lo",
|
||||||
|
"url": "https://pleroma.example.org/users/user",
|
||||||
|
"username": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"acct": "admin",
|
||||||
|
"id": "9hEkA5JsvAdlSrocam",
|
||||||
|
"url": "https://pleroma.example.org/users/admin",
|
||||||
|
"username": "admin"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"muted": false,
|
||||||
|
"pinned": false,
|
||||||
|
"pleroma": {
|
||||||
|
"content": {
|
||||||
|
"text/plain": "Your claim is going to be closed"
|
||||||
|
},
|
||||||
|
"conversation_id": 35,
|
||||||
|
"in_reply_to_account_acct": null,
|
||||||
|
"local": true,
|
||||||
|
"spoiler_text": {
|
||||||
|
"text/plain": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reblog": null,
|
||||||
|
"reblogged": false,
|
||||||
|
"reblogs_count": 0,
|
||||||
|
"replies_count": 0,
|
||||||
|
"sensitive": false,
|
||||||
|
"spoiler_text": "",
|
||||||
|
"tags": [],
|
||||||
|
"uri": "https://pleroma.example.org/objects/cab0836d-9814-46cd-a0ea-529da9db5fcb",
|
||||||
|
"url": "https://pleroma.example.org/notice/9ihuiSL1405I65TmEq",
|
||||||
|
"visibility": "direct"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/statuses/:id`
|
||||||
|
### Change the scope of an individual reported status
|
||||||
|
- Method `PUT`
|
||||||
|
- Params:
|
||||||
|
- `id`
|
||||||
|
- `sensitive`: optional, valid values are `true` or `false`
|
||||||
|
- `visibility`: optional, valid values are `public`, `private` and `unlisted`
|
||||||
|
- Response:
|
||||||
|
- On failure:
|
||||||
|
- 400 Bad Request `"Unsupported visibility"`
|
||||||
|
- 403 Forbidden `{"error": "error_msg"}`
|
||||||
|
- 404 Not Found `"Not found"`
|
||||||
|
- On success: JSON, Mastodon Status entity
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/statuses/:id`
|
||||||
|
### Delete an individual reported status
|
||||||
|
- Method `DELETE`
|
||||||
|
- Params:
|
||||||
|
- `id`
|
||||||
|
- Response:
|
||||||
|
- On failure:
|
||||||
|
- 403 Forbidden `{"error": "error_msg"}`
|
||||||
|
- 404 Not Found `"Not found"`
|
||||||
|
- On success: 200 OK `{}`
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/config`
|
||||||
|
### List config settings
|
||||||
|
- Method `GET`
|
||||||
|
- Params: none
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
configs: [
|
||||||
|
{
|
||||||
|
"group": string,
|
||||||
|
"key": string,
|
||||||
|
"value": string or {} or [] or {"tuple": []}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/config`
|
||||||
|
### Update config settings
|
||||||
|
Module name can be passed as string, which starts with `Pleroma`, e.g. `"Pleroma.Upload"`.
|
||||||
|
Atom or boolean value can be passed with `:` in the beginning, e.g. `":true"`, `":upload"`. For keys it is not needed.
|
||||||
|
Integer with `i:`, e.g. `"i:150"`.
|
||||||
|
Tuple with more than 2 values with `{"tuple": ["first_val", Pleroma.Module, []]}`.
|
||||||
|
`{"tuple": ["some_string", "Pleroma.Some.Module", []]}` will be converted to `{"some_string", Pleroma.Some.Module, []}`.
|
||||||
|
|
||||||
|
Compile time settings (need instance reboot):
|
||||||
|
- all settings by this keys:
|
||||||
|
- `:hackney_pools`
|
||||||
|
- `:chat`
|
||||||
|
- `Pleroma.Web.Endpoint`
|
||||||
|
- `Pleroma.Repo`
|
||||||
|
- part settings:
|
||||||
|
- `Pleroma.Captcha` -> `:seconds_valid`
|
||||||
|
- `Pleroma.Upload` -> `:proxy_remote`
|
||||||
|
- `:instance` -> `:upload_limit`
|
||||||
|
|
||||||
|
- Method `POST`
|
||||||
|
- Params:
|
||||||
|
- `configs` => [
|
||||||
|
- `group` (string)
|
||||||
|
- `key` (string)
|
||||||
|
- `value` (string, [], {} or {"tuple": []})
|
||||||
|
- `delete` = true (optional, if parameter must be deleted)
|
||||||
|
]
|
||||||
|
|
||||||
|
- Request (example):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
configs: [
|
||||||
|
{
|
||||||
|
"group": "pleroma",
|
||||||
|
"key": "Pleroma.Upload",
|
||||||
|
"value": {
|
||||||
|
"uploader": "Pleroma.Uploaders.Local",
|
||||||
|
"filters": ["Pleroma.Upload.Filter.Dedupe"],
|
||||||
|
"link_name": ":true",
|
||||||
|
"proxy_remote": ":false",
|
||||||
|
"proxy_opts": {
|
||||||
|
"redirect_on_failure": ":false",
|
||||||
|
"max_body_length": "i:1048576",
|
||||||
|
"http": {
|
||||||
|
"follow_redirect": ":true",
|
||||||
|
"pool": ":upload"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dispatch": {
|
||||||
|
"tuple": ["/api/v1/streaming", "Pleroma.Web.MastodonAPI.WebsocketHandler", []]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
- Response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
configs: [
|
||||||
|
{
|
||||||
|
"group": string,
|
||||||
|
"key": string,
|
||||||
|
"value": string or {} or [] or {"tuple": []}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,112 @@
|
||||||
|
# Differences in Mastodon API responses from vanilla Mastodon
|
||||||
|
|
||||||
|
A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance`
|
||||||
|
|
||||||
|
## Flake IDs
|
||||||
|
|
||||||
|
Pleroma uses 128-bit ids as opposed to Mastodon's 64 bits. However just like Mastodon's ids they are sortable strings
|
||||||
|
|
||||||
|
## Attachment cap
|
||||||
|
|
||||||
|
Some apps operate under the assumption that no more than 4 attachments can be returned or uploaded. Pleroma however does not enforce any limits on attachment count neither when returning the status object nor when posting.
|
||||||
|
|
||||||
|
## Timelines
|
||||||
|
|
||||||
|
Adding the parameter `with_muted=true` to the timeline queries will also return activities by muted (not by blocked!) users.
|
||||||
|
|
||||||
|
## Statuses
|
||||||
|
|
||||||
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
|
- `local`: true if the post was made on the local instance.
|
||||||
|
- `conversation_id`: the ID of the conversation the status is associated with (if any)
|
||||||
|
- `in_reply_to_account_acct`: the `acct` property of User entity for replied user (if any)
|
||||||
|
- `content`: a map consisting of alternate representations of the `content` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`
|
||||||
|
- `spoiler_text`: a map consisting of alternate representations of the `spoiler_text` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`
|
||||||
|
|
||||||
|
## Attachments
|
||||||
|
|
||||||
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
|
- `mime_type`: mime type of the attachment.
|
||||||
|
|
||||||
|
## Accounts
|
||||||
|
|
||||||
|
- `/api/v1/accounts/:id`: The `id` parameter can also be the `nickname` of the user. This only works in this endpoint, not the deeper nested ones for following etc.
|
||||||
|
|
||||||
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
|
- `tags`: Lists an array of tags for the user
|
||||||
|
- `relationship{}`: Includes fields as documented for Mastodon API https://docs.joinmastodon.org/api/entities/#relationship
|
||||||
|
- `is_moderator`: boolean, nullable, true if user is a moderator
|
||||||
|
- `is_admin`: boolean, nullable, true if user is an admin
|
||||||
|
- `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
|
||||||
|
- `hide_followers`: boolean, true when the user has follower hiding enabled
|
||||||
|
- `hide_follows`: boolean, true when the user has follow hiding enabled
|
||||||
|
- `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`
|
||||||
|
- `chat_token`: The token needed for Pleroma chat. Only returned in `verify_credentials`
|
||||||
|
|
||||||
|
### Source
|
||||||
|
|
||||||
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
|
- `show_role`: boolean, nullable, true when the user wants his role (e.g admin, moderator) to be shown
|
||||||
|
- `no_rich_text` - boolean, nullable, true when html tags are stripped from all statuses requested from the API
|
||||||
|
|
||||||
|
## Account Search
|
||||||
|
|
||||||
|
Behavior has changed:
|
||||||
|
|
||||||
|
- `/api/v1/accounts/search`: Does not require authentication
|
||||||
|
|
||||||
|
## Notifications
|
||||||
|
|
||||||
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
|
- `is_seen`: true if the notification was read by the user
|
||||||
|
|
||||||
|
## POST `/api/v1/statuses`
|
||||||
|
|
||||||
|
Additional parameters can be added to the JSON body/Form data:
|
||||||
|
|
||||||
|
- `preview`: boolean, if set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example.
|
||||||
|
- `content_type`: string, contain the MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint.
|
||||||
|
- `to`: A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for for post visibility are not affected by this and will still apply.
|
||||||
|
|
||||||
|
## PATCH `/api/v1/update_credentials`
|
||||||
|
|
||||||
|
Additional parameters can be added to the JSON body/Form data:
|
||||||
|
|
||||||
|
- `no_rich_text` - if true, html tags are stripped from all statuses requested from the API
|
||||||
|
- `hide_followers` - if true, user's followers will be hidden
|
||||||
|
- `hide_follows` - if true, user's follows will be hidden
|
||||||
|
- `hide_favorites` - if true, user's favorites timeline will be hidden
|
||||||
|
- `show_role` - if true, user's role (e.g admin, moderator) will be exposed to anyone in the API
|
||||||
|
- `default_scope` - the scope returned under `privacy` key in Source subentity
|
||||||
|
- `pleroma_settings_store` - Opaque user settings to be saved on the backend.
|
||||||
|
- `skip_thread_containment` - if true, skip filtering out broken threads
|
||||||
|
- `pleroma_background_image` - sets the background image of the user.
|
||||||
|
|
||||||
|
### Pleroma Settings Store
|
||||||
|
Pleroma has mechanism that allows frontends to save blobs of json for each user on the backend. This can be used to save frontend-specific settings for a user that the backend does not need to know about.
|
||||||
|
|
||||||
|
The parameter should have a form of `{frontend_name: {...}}`, with `frontend_name` identifying your type of client, e.g. `pleroma_fe`. It will overwrite everything under this property, but will not overwrite other frontend's settings.
|
||||||
|
|
||||||
|
This information is returned in the `verify_credentials` endpoint.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
*Pleroma supports refreshing tokens.
|
||||||
|
|
||||||
|
`POST /oauth/token`
|
||||||
|
Post here request with grant_type=refresh_token to obtain new access token. Returns an access token.
|
||||||
|
|
||||||
|
## Account Registration
|
||||||
|
`POST /api/v1/accounts`
|
||||||
|
|
||||||
|
Has theses additionnal parameters (which are the same as in Pleroma-API):
|
||||||
|
* `fullname`: optional
|
||||||
|
* `bio`: optional
|
||||||
|
* `captcha_solution`: optional, contains provider-specific captcha solution,
|
||||||
|
* `captcha_token`: optional, contains provider-specific captcha token
|
||||||
|
* `token`: invite token required when the registerations aren't public.
|
|
@ -0,0 +1,306 @@
|
||||||
|
# Pleroma API
|
||||||
|
|
||||||
|
Requests that require it can be authenticated with [an OAuth token](https://tools.ietf.org/html/rfc6749), the `_pleroma_key` cookie, or [HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization).
|
||||||
|
|
||||||
|
Request parameters can be passed via [query strings](https://en.wikipedia.org/wiki/Query_string) or as [form data](https://www.w3.org/TR/html401/interact/forms.html). Files must be uploaded as `multipart/form-data`.
|
||||||
|
|
||||||
|
## `/api/pleroma/emoji`
|
||||||
|
### Lists the custom emoji on that server.
|
||||||
|
* Method: `GET`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params: none
|
||||||
|
* Response: JSON
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"girlpower": {
|
||||||
|
"tags": [
|
||||||
|
"Finmoji"
|
||||||
|
],
|
||||||
|
"image_url": "/finmoji/128px/girlpower-128.png"
|
||||||
|
},
|
||||||
|
"education": {
|
||||||
|
"tags": [
|
||||||
|
"Finmoji"
|
||||||
|
],
|
||||||
|
"image_url": "/finmoji/128px/education-128.png"
|
||||||
|
},
|
||||||
|
"finnishlove": {
|
||||||
|
"tags": [
|
||||||
|
"Finmoji"
|
||||||
|
],
|
||||||
|
"image_url": "/finmoji/128px/finnishlove-128.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* Note: Same data as Mastodon API’s `/api/v1/custom_emojis` but in a different format
|
||||||
|
|
||||||
|
## `/api/pleroma/follow_import`
|
||||||
|
### Imports your follows, for example from a Mastodon CSV file.
|
||||||
|
* Method: `POST`
|
||||||
|
* Authentication: required
|
||||||
|
* Params:
|
||||||
|
* `list`: STRING or FILE containing a whitespace-separated list of accounts to follow
|
||||||
|
* Response: HTTP 200 on success, 500 on error
|
||||||
|
* Note: Users that can't be followed are silently skipped.
|
||||||
|
|
||||||
|
## `/api/pleroma/captcha`
|
||||||
|
### Get a new captcha
|
||||||
|
* Method: `GET`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params: none
|
||||||
|
* Response: Provider specific JSON, the only guaranteed parameter is `type`
|
||||||
|
* Example response: `{"type": "kocaptcha", "token": "whatever", "url": "https://captcha.kotobank.ch/endpoint"}`
|
||||||
|
|
||||||
|
## `/api/pleroma/delete_account`
|
||||||
|
### Delete an account
|
||||||
|
* Method `POST`
|
||||||
|
* Authentication: required
|
||||||
|
* Params:
|
||||||
|
* `password`: user's password
|
||||||
|
* Response: JSON. Returns `{"status": "success"}` if the deletion was successful, `{"error": "[error message]"}` otherwise
|
||||||
|
* Example response: `{"error": "Invalid password."}`
|
||||||
|
|
||||||
|
## `/api/pleroma/disable_account`
|
||||||
|
### Disable an account
|
||||||
|
* Method `POST`
|
||||||
|
* Authentication: required
|
||||||
|
* Params:
|
||||||
|
* `password`: user's password
|
||||||
|
* Response: JSON. Returns `{"status": "success"}` if the account was successfully disabled, `{"error": "[error message]"}` otherwise
|
||||||
|
* Example response: `{"error": "Invalid password."}`
|
||||||
|
|
||||||
|
## `/api/account/register`
|
||||||
|
### Register a new user
|
||||||
|
* Method `POST`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params:
|
||||||
|
* `nickname`
|
||||||
|
* `fullname`
|
||||||
|
* `bio`
|
||||||
|
* `email`
|
||||||
|
* `password`
|
||||||
|
* `confirm`
|
||||||
|
* `captcha_solution`: optional, contains provider-specific captcha solution,
|
||||||
|
* `captcha_token`: optional, contains provider-specific captcha token
|
||||||
|
* `token`: invite token required when the registrations aren't public.
|
||||||
|
* Response: JSON. Returns a user object on success, otherwise returns `{"error": "error_msg"}`
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"background_image": null,
|
||||||
|
"cover_photo": "https://pleroma.soykaf.com/images/banner.png",
|
||||||
|
"created_at": "Tue Dec 18 16:55:56 +0000 2018",
|
||||||
|
"default_scope": "public",
|
||||||
|
"description": "blushy-crushy fediverse idol + pleroma dev\nlet's be friends \nぷれろまの生徒会長。謎の外人。日本語OK. \n公主病.",
|
||||||
|
"description_html": "blushy-crushy fediverse idol + pleroma dev.<br />let's be friends <br />ぷれろまの生徒会長。謎の外人。日本語OK. <br />公主病.",
|
||||||
|
"favourites_count": 0,
|
||||||
|
"fields": [],
|
||||||
|
"followers_count": 0,
|
||||||
|
"following": false,
|
||||||
|
"follows_you": false,
|
||||||
|
"friends_count": 0,
|
||||||
|
"id": 6,
|
||||||
|
"is_local": true,
|
||||||
|
"locked": false,
|
||||||
|
"name": "lain",
|
||||||
|
"name_html": "lain",
|
||||||
|
"no_rich_text": false,
|
||||||
|
"pleroma": {
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
"profile_image_url": "https://pleroma.soykaf.com/images/avi.png",
|
||||||
|
"profile_image_url_https": "https://pleroma.soykaf.com/images/avi.png",
|
||||||
|
"profile_image_url_original": "https://pleroma.soykaf.com/images/avi.png",
|
||||||
|
"profile_image_url_profile_size": "https://pleroma.soykaf.com/images/avi.png",
|
||||||
|
"rights": {
|
||||||
|
"delete_others_notice": false
|
||||||
|
},
|
||||||
|
"screen_name": "lain",
|
||||||
|
"statuses_count": 0,
|
||||||
|
"statusnet_blocking": false,
|
||||||
|
"statusnet_profile_url": "https://pleroma.soykaf.com/users/lain"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/pleroma/admin/`…
|
||||||
|
See [Admin-API](Admin-API.md)
|
||||||
|
|
||||||
|
## `/api/pleroma/notifications/read`
|
||||||
|
### Mark a single notification as read
|
||||||
|
* Method `POST`
|
||||||
|
* Authentication: required
|
||||||
|
* Params:
|
||||||
|
* `id`: notification's id
|
||||||
|
* Response: JSON. Returns `{"status": "success"}` if the reading was successful, otherwise returns `{"error": "error_msg"}`
|
||||||
|
|
||||||
|
## `/api/v1/pleroma/accounts/:id/subscribe`
|
||||||
|
### Subscribe to receive notifications for all statuses posted by a user
|
||||||
|
* Method `POST`
|
||||||
|
* Authentication: required
|
||||||
|
* Params:
|
||||||
|
* `id`: account id to subscribe to
|
||||||
|
* Response: JSON, returns a mastodon relationship object on success, otherwise returns `{"error": "error_msg"}`
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "abcdefg",
|
||||||
|
"following": true,
|
||||||
|
"followed_by": false,
|
||||||
|
"blocking": false,
|
||||||
|
"muting": false,
|
||||||
|
"muting_notifications": false,
|
||||||
|
"subscribing": true,
|
||||||
|
"requested": false,
|
||||||
|
"domain_blocking": false,
|
||||||
|
"showing_reblogs": true,
|
||||||
|
"endorsed": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/v1/pleroma/accounts/:id/unsubscribe`
|
||||||
|
### Unsubscribe to stop receiving notifications from user statuses
|
||||||
|
* Method `POST`
|
||||||
|
* Authentication: required
|
||||||
|
* Params:
|
||||||
|
* `id`: account id to unsubscribe from
|
||||||
|
* Response: JSON, returns a mastodon relationship object on success, otherwise returns `{"error": "error_msg"}`
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "abcdefg",
|
||||||
|
"following": true,
|
||||||
|
"followed_by": false,
|
||||||
|
"blocking": false,
|
||||||
|
"muting": false,
|
||||||
|
"muting_notifications": false,
|
||||||
|
"subscribing": false,
|
||||||
|
"requested": false,
|
||||||
|
"domain_blocking": false,
|
||||||
|
"showing_reblogs": true,
|
||||||
|
"endorsed": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/v1/pleroma/accounts/:id/favourites`
|
||||||
|
### Returns favorites timeline of any user
|
||||||
|
* Method `GET`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params:
|
||||||
|
* `id`: the id of the account for whom to return results
|
||||||
|
* `limit`: optional, the number of records to retrieve
|
||||||
|
* `since_id`: optional, returns results that are more recent than the specified id
|
||||||
|
* `max_id`: optional, returns results that are older than the specified id
|
||||||
|
* Response: JSON, returns a list of Mastodon Status entities on success, otherwise returns `{"error": "error_msg"}`
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"id": "9hptFmUF3ztxYh3Svg",
|
||||||
|
"url": "https://pleroma.example.org/users/nick2",
|
||||||
|
"username": "nick2",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
"application": {"name": "Web", "website": null},
|
||||||
|
"bookmarked": false,
|
||||||
|
"card": null,
|
||||||
|
"content": "This is :moominmamma: note 0",
|
||||||
|
"created_at": "2019-04-15T15:42:15.000Z",
|
||||||
|
"emojis": [],
|
||||||
|
"favourited": false,
|
||||||
|
"favourites_count": 1,
|
||||||
|
"id": "9hptFmVJ02khbzYJaS",
|
||||||
|
"in_reply_to_account_id": null,
|
||||||
|
"in_reply_to_id": null,
|
||||||
|
"language": null,
|
||||||
|
"media_attachments": [],
|
||||||
|
"mentions": [],
|
||||||
|
"muted": false,
|
||||||
|
"pinned": false,
|
||||||
|
"pleroma": {
|
||||||
|
"content": {"text/plain": "This is :moominmamma: note 0"},
|
||||||
|
"conversation_id": 13679,
|
||||||
|
"local": true,
|
||||||
|
"spoiler_text": {"text/plain": "2hu"}
|
||||||
|
},
|
||||||
|
"reblog": null,
|
||||||
|
"reblogged": false,
|
||||||
|
"reblogs_count": 0,
|
||||||
|
"replies_count": 0,
|
||||||
|
"sensitive": false,
|
||||||
|
"spoiler_text": "2hu",
|
||||||
|
"tags": [{"name": "2hu", "url": "/tag/2hu"}],
|
||||||
|
"uri": "https://pleroma.example.org/objects/198ed2a1-7912-4482-b559-244a0369e984",
|
||||||
|
"url": "https://pleroma.example.org/notice/9hptFmVJ02khbzYJaS",
|
||||||
|
"visibility": "public"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/api/v1/pleroma/mascot`
|
||||||
|
### Gets user mascot image
|
||||||
|
* Method `GET`
|
||||||
|
* Authentication: required
|
||||||
|
|
||||||
|
* Response: JSON. Returns a mastodon media attachment entity.
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "abcdefg",
|
||||||
|
"url": "https://pleroma.example.org/media/abcdefg.png",
|
||||||
|
"type": "image",
|
||||||
|
"pleroma": {
|
||||||
|
"mime_type": "image/png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Updates user mascot image
|
||||||
|
* Method `PUT`
|
||||||
|
* Authentication: required
|
||||||
|
* Params:
|
||||||
|
* `image`: Multipart image
|
||||||
|
* Response: JSON. Returns a mastodon media attachment entity
|
||||||
|
when successful, otherwise returns HTTP 415 `{"error": "error_msg"}`
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "abcdefg",
|
||||||
|
"url": "https://pleroma.example.org/media/abcdefg.png",
|
||||||
|
"type": "image",
|
||||||
|
"pleroma": {
|
||||||
|
"mime_type": "image/png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* Note: Behaves exactly the same as `POST /api/v1/upload`.
|
||||||
|
Can only accept images - any attempt to upload non-image files will be met with `HTTP 415 Unsupported Media Type`.
|
||||||
|
|
||||||
|
## `/api/pleroma/notification_settings`
|
||||||
|
### Updates user notification settings
|
||||||
|
* Method `PUT`
|
||||||
|
* Authentication: required
|
||||||
|
* Params:
|
||||||
|
* `followers`: BOOLEAN field, receives notifications from followers
|
||||||
|
* `follows`: BOOLEAN field, receives notifications from people the user follows
|
||||||
|
* `remote`: BOOLEAN field, receives notifications from people on remote instances
|
||||||
|
* `local`: BOOLEAN field, receives notifications from people on the local instance
|
||||||
|
* Response: JSON. Returns `{"status": "success"}` if the update was successful, otherwise returns `{"error": "error_msg"}`
|
||||||
|
|
||||||
|
## `/api/pleroma/healthcheck`
|
||||||
|
### Healthcheck endpoint with additional system data.
|
||||||
|
* Method `GET`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params: none
|
||||||
|
* Response: JSON, statuses (200 - healthy, 503 unhealthy).
|
||||||
|
* Example response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pool_size": 0, # database connection pool
|
||||||
|
"active": 0, # active processes
|
||||||
|
"idle": 0, # idle processes
|
||||||
|
"memory_used": 0.00, # Memory used
|
||||||
|
"healthy": true # Instance state
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Prometheus Metrics
|
||||||
|
|
||||||
|
Pleroma includes support for exporting metrics via the [prometheus_ex](https://github.com/deadtrickster/prometheus.ex) library.
|
||||||
|
|
||||||
|
## `/api/pleroma/app_metrics`
|
||||||
|
### Exports Prometheus application metrics
|
||||||
|
* Method: `GET`
|
||||||
|
* Authentication: not required
|
||||||
|
* Params: none
|
||||||
|
* Response: JSON
|
||||||
|
|
||||||
|
## Grafana
|
||||||
|
### Config example
|
||||||
|
The following is a config example to use with [Grafana](https://grafana.com)
|
||||||
|
|
||||||
|
```
|
||||||
|
- job_name: 'beam'
|
||||||
|
metrics_path: /api/pleroma/app_metrics
|
||||||
|
scheme: https
|
||||||
|
static_configs:
|
||||||
|
- targets: ['pleroma.soykaf.com']
|
||||||
|
```
|
|
@ -1,124 +1,94 @@
|
||||||
# Pleroma Clients
|
# Pleroma Clients
|
||||||
Note: Additional clients may be working but theses are officially supporting Pleroma.
|
Note: Additionnal clients may be working but theses are officially supporting Pleroma.
|
||||||
Feel free to contact us to be added to this list!
|
Feel free to contact us to be added to this list!
|
||||||
|
|
||||||
## Desktop
|
## Desktop
|
||||||
### Roma for Desktop
|
### Roma for Desktop
|
||||||
- Homepage: <https://www.pleroma.com/#desktopApp>
|
- Homepage: <https://www.pleroma.com/#desktopApp>
|
||||||
- Source Code: <https://github.com/roma-apps/roma-desktop>
|
- Source Code: <https://github.com/roma-apps/roma-desktop>
|
||||||
- Platforms: Windows, Mac, Linux
|
- Platforms: Windows, Mac, (Linux?)
|
||||||
- Features: MastoAPI, Streaming Ready
|
- Features: Streaming Ready
|
||||||
|
|
||||||
### Social
|
### Social
|
||||||
- Source Code: <https://gitlab.gnome.org/World/Social>
|
- Source Code: <https://gitlab.gnome.org/BrainBlasted/Social>
|
||||||
- Contact: [@brainblasted@social.libre.fi](https://social.libre.fi/users/brainblasted)
|
- Contact: [@brainblasted@social.libre.fi](https://social.libre.fi/users/brainblasted)
|
||||||
- Platforms: Linux (GNOME)
|
- Platforms: Linux (GNOME)
|
||||||
- Note(2019-01-28): Not at a pre-alpha stage yet
|
- Note(2019-01-28): Not at a pre-alpha stage yet
|
||||||
- Features: MastoAPI
|
|
||||||
|
|
||||||
### Whalebird
|
### Whalebird
|
||||||
- Homepage: <https://whalebird.social/>
|
- Homepage: <https://whalebird.org/>
|
||||||
- Source Code: <https://github.com/h3poteto/whalebird-desktop>
|
- Source Code: <https://github.com/h3poteto/whalebird-desktop>
|
||||||
- Contact: [@h3poteto@pleroma.io](https://pleroma.io/users/h3poteto)
|
- Contact: [@h3poteto@pleroma.io](https://pleroma.io/users/h3poteto)
|
||||||
- Platforms: Windows, Mac, Linux
|
- Platforms: Windows, Mac, Linux
|
||||||
- Features: MastoAPI, Streaming Ready
|
- Features: Streaming Ready
|
||||||
|
|
||||||
## Handheld
|
## Handheld
|
||||||
### AndStatus
|
|
||||||
- Homepage: <http://andstatus.org/>
|
|
||||||
- Source Code: <https://github.com/andstatus/andstatus/>
|
|
||||||
- Platforms: Android
|
|
||||||
- Features: MastoAPI, ActivityPub (Client-to-Server)
|
|
||||||
|
|
||||||
### Amaroq
|
### Amaroq
|
||||||
- Homepage: <https://itunes.apple.com/us/app/amaroq-for-mastodon/id1214116200>
|
- Homepage: <https://itunes.apple.com/us/app/amaroq-for-mastodon/id1214116200>
|
||||||
- Source Code: <https://github.com/ReticentJohn/Amaroq>
|
- Source Code: <https://github.com/ReticentJohn/Amaroq>
|
||||||
- Contact: [@eurasierboy@mastodon.social](https://mastodon.social/users/eurasierboy)
|
- Contact: [@eurasierboy@mastodon.social](https://mastodon.social/users/eurasierboy)
|
||||||
- Platforms: iOS
|
- Platforms: iOS
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: No Streaming
|
||||||
|
|
||||||
### Fedilab
|
### Fedilab
|
||||||
- Homepage: <https://fedilab.app/>
|
- Homepage: <https://fedilab.app/>
|
||||||
- Source Code: <https://framagit.org/tom79/fedilab/>
|
- Source Code: <https://framagit.org/tom79/fedilab/>
|
||||||
- Contact: [@fedilab@framapiaf.org](https://framapiaf.org/users/fedilab)
|
- Contact: [@fedilab@framapiaf.org](https://framapiaf.org/users/fedilab)
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: MastoAPI, Streaming Ready, Moderation, Text Formatting
|
- Features: Streaming Ready, Moderation, Text Formatting
|
||||||
|
|
||||||
### Kyclos
|
### Nekonium
|
||||||
- Source Code: <https://git.pleroma.social/pleroma/harbour-kyclos>
|
- Homepage: [F-Droid Repository](https://repo.gdgd.jp.net/), [Google Play](https://play.google.com/store/apps/details?id=com.apps.nekonium), [Amazon](https://www.amazon.co.jp/dp/B076FXPRBC/)
|
||||||
- Platforms: SailfishOS
|
- Source: <https://git.gdgd.jp.net/lin/nekonium/>
|
||||||
- Features: MastoAPI, No Streaming
|
- Contact: [@lin@pleroma.gdgd.jp.net](https://pleroma.gdgd.jp.net/users/lin)
|
||||||
|
|
||||||
### Husky
|
|
||||||
- Source code: <https://git.mentality.rip/FWGS/Husky>
|
|
||||||
- Contact: [@Husky@enigmatic.observer](https://enigmatic.observer/users/Husky)
|
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: MastoAPI, No Streaming, Emoji Reactions, Text Formatting, FE Stickers
|
- Features: Streaming Ready
|
||||||
|
|
||||||
### Fedi
|
### Roma
|
||||||
- Homepage: <https://www.fediapp.com/>
|
- Homepage: <https://www.pleroma.com/#mobileApps>
|
||||||
- Source Code: Proprietary, but gratis
|
- Source Code: [iOS](https://github.com/roma-apps/roma-ios), [Android](https://github.com/roma-apps/roma-android)
|
||||||
- Platforms: iOS, Android
|
- Platforms: iOS, Android
|
||||||
- Features: MastoAPI, Pleroma-specific features like Reactions
|
- Features: No Streaming
|
||||||
|
|
||||||
### Tusky
|
### Tusky
|
||||||
- Homepage: <https://tuskyapp.github.io/>
|
- Homepage: <https://tuskyapp.github.io/>
|
||||||
- Source Code: <https://github.com/tuskyapp/Tusky>
|
- Source Code: <https://github.com/tuskyapp/Tusky>
|
||||||
- Contact: [@ConnyDuck@mastodon.social](https://mastodon.social/users/ConnyDuck)
|
- Contact: [@ConnyDuck@mastodon.social](https://mastodon.social/users/ConnyDuck)
|
||||||
- Platforms: Android
|
- Platforms: Android
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: No Streaming
|
||||||
|
|
||||||
### Twidere
|
### Twidere
|
||||||
- Homepage: <https://twidere.mariotaku.org/>
|
- Homepage: <https://twidere.mariotaku.org/>
|
||||||
- Source Code: <https://github.com/TwidereProject/Twidere-Android/>
|
- Source Code: <https://github.com/TwidereProject/Twidere-Android/>, <https://github.com/TwidereProject/Twidere-iOS/>
|
||||||
- Contact: <me@mariotaku.org>
|
- Contact: <me@mariotaku.org>
|
||||||
- Platform: Android
|
- Platform: Android, iOS
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: No Streaming
|
||||||
|
|
||||||
### Indigenous
|
|
||||||
- Homepage: <https://indigenous.realize.be/>
|
|
||||||
- Source Code: <https://github.com/swentel/indigenous-android/>
|
|
||||||
- Contact: [@swentel@realize.be](https://realize.be)
|
|
||||||
- Platforms: Android
|
|
||||||
- Features: MastoAPI, No Streaming
|
|
||||||
|
|
||||||
## Alternative Web Interfaces
|
## Alternative Web Interfaces
|
||||||
### Brutaldon
|
### Brutaldon
|
||||||
- Homepage: <https://jfm.carcosa.net/projects/software/brutaldon/>
|
- Homepage: <https://jfm.carcosa.net/projects/software/brutaldon/>
|
||||||
- Source Code: <https://git.carcosa.net/jmcbray/brutaldon>
|
- Source Code: <https://github.com/jfmcbrayer/brutaldon>
|
||||||
- Contact: [@gcupc@glitch.social](https://glitch.social/users/gcupc)
|
- Contact: [@gcupc@glitch.social](https://glitch.social/users/gcupc)
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: No Streaming
|
||||||
|
|
||||||
|
### Feather
|
||||||
|
- Source Code: <https://github.com/kaniini/feather>
|
||||||
|
- Contact: [@kaniini@pleroma.site](https://pleroma.site/kaniini)
|
||||||
|
- Features: No Streaming
|
||||||
|
|
||||||
### Halcyon
|
### Halcyon
|
||||||
- Source Code: <https://notabug.org/halcyon-suite/halcyon>
|
- Source Code: <https://notabug.org/halcyon-suite/halcyon>
|
||||||
- Contact: [@halcyon@social.csswg.org](https://social.csswg.org/users/halcyon)
|
- Contact: [@halcyon@social.csswg.org](https://social.csswg.org/users/halcyon)
|
||||||
- Features: MastoAPI, Streaming Ready
|
- Features: Streaming Ready
|
||||||
|
|
||||||
### Pinafore
|
### Pinafore
|
||||||
- Homepage: <https://pinafore.social/>
|
- Homepage: <https://pinafore.social/>
|
||||||
- Source Code: <https://github.com/nolanlawson/pinafore>
|
- Source Code: <https://github.com/nolanlawson/pinafore>
|
||||||
- Contact: [@pinafore@mastodon.technology](https://mastodon.technology/users/pinafore)
|
- Contact: [@pinafore@mastodon.technology](https://mastodon.technology/users/pinafore)
|
||||||
- Note: Pleroma support is a secondary goal
|
- Note: Pleroma support is a secondary goal
|
||||||
- Features: MastoAPI, No Streaming
|
- Features: No Streaming
|
||||||
|
|
||||||
### Sengi
|
### Sengi
|
||||||
- Homepage: <https://nicolasconstant.github.io/sengi/>
|
|
||||||
- Source Code: <https://github.com/NicolasConstant/sengi>
|
- Source Code: <https://github.com/NicolasConstant/sengi>
|
||||||
- Contact: [@sengi_app@mastodon.social](https://mastodon.social/users/sengi_app)
|
- Contact: [@sengi_app@mastodon.social](https://mastodon.social/users/sengi_app)
|
||||||
- Features: MastoAPI
|
- Note(2019-01-28): The development is currently in a early stage.
|
||||||
|
|
||||||
### DashFE
|
|
||||||
- Source Code: <https://notabug.org/daisuke/DashboardFE>
|
|
||||||
- Contact: [@dashfe@stereophonic.space](https://stereophonic.space/users/dashfe)
|
|
||||||
|
|
||||||
### BloatFE
|
|
||||||
- Source Code: <https://git.freesoftwareextremist.com/bloat/>
|
|
||||||
- Contact: [@r@freesoftwareextremist.com](https://freesoftwareextremist.com/users/r)
|
|
||||||
- Features: Does not requires JavaScript
|
|
||||||
- Features: MastoAPI
|
|
||||||
|
|
||||||
### Glitch-lily
|
|
||||||
- Source Code: <https://lily.kazv.moe/infra/glitch-lily>
|
|
||||||
- Contact: [@tusooa@kazv.moe](https://kazv.moe/users/tusooa)
|
|
||||||
- Features: MastoAPI
|
|
||||||
- Based on [glitch-soc](https://github.com/glitch-soc/mastodon) frontend
|
|
||||||
|
|
|
@ -0,0 +1,643 @@
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
This file describe the configuration, it is recommended to edit the relevant *.secret.exs file instead of the others founds in the ``config`` directory.
|
||||||
|
If you run Pleroma with ``MIX_ENV=prod`` the file is ``prod.secret.exs``, otherwise it is ``dev.secret.exs``.
|
||||||
|
|
||||||
|
## Pleroma.Upload
|
||||||
|
* `uploader`: Select which `Pleroma.Uploaders` to use
|
||||||
|
* `filters`: List of `Pleroma.Upload.Filter` to use.
|
||||||
|
* `link_name`: When enabled Pleroma will add a `name` parameter to the url of the upload, for example `https://instance.tld/media/corndog.png?name=corndog.png`. This is needed to provide the correct filename in Content-Disposition headers when using filters like `Pleroma.Upload.Filter.Dedupe`
|
||||||
|
* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host.
|
||||||
|
* `proxy_remote`: If you\'re using a remote uploader, Pleroma will proxy media requests instead of redirecting to it.
|
||||||
|
* `proxy_opts`: Proxy options, see `Pleroma.ReverseProxy` documentation.
|
||||||
|
|
||||||
|
Note: `strip_exif` has been replaced by `Pleroma.Upload.Filter.Mogrify`.
|
||||||
|
|
||||||
|
## Pleroma.Uploaders.Local
|
||||||
|
* `uploads`: Which directory to store the user-uploads in, relative to pleroma’s working directory
|
||||||
|
|
||||||
|
## Pleroma.Uploaders.S3
|
||||||
|
* `bucket`: S3 bucket name
|
||||||
|
* `public_endpoint`: S3 endpoint that the user finally accesses(ex. "https://s3.dualstack.ap-northeast-1.amazonaws.com")
|
||||||
|
* `truncated_namespace`: If you use S3 compatible service such as Digital Ocean Spaces or CDN, set folder name or "" etc.
|
||||||
|
For example, when using CDN to S3 virtual host format, set "".
|
||||||
|
At this time, write CNAME to CDN in public_endpoint.
|
||||||
|
|
||||||
|
## Pleroma.Upload.Filter.Mogrify
|
||||||
|
|
||||||
|
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"impode", "1"}]`.
|
||||||
|
|
||||||
|
## Pleroma.Upload.Filter.Dedupe
|
||||||
|
|
||||||
|
No specific configuration.
|
||||||
|
|
||||||
|
## Pleroma.Upload.Filter.AnonymizeFilename
|
||||||
|
|
||||||
|
This filter replaces the filename (not the path) of an upload. For complete obfuscation, add
|
||||||
|
`Pleroma.Upload.Filter.Dedupe` before AnonymizeFilename.
|
||||||
|
|
||||||
|
* `text`: Text to replace filenames in links. If empty, `{random}.extension` will be used.
|
||||||
|
|
||||||
|
## Pleroma.Emails.Mailer
|
||||||
|
* `adapter`: one of the mail adapters listed in [Swoosh readme](https://github.com/swoosh/swoosh#adapters), or `Swoosh.Adapters.Local` for in-memory mailbox.
|
||||||
|
* `api_key` / `password` and / or other adapter-specific settings, per the above documentation.
|
||||||
|
|
||||||
|
An example for Sendgrid adapter:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, Pleroma.Emails.Mailer,
|
||||||
|
adapter: Swoosh.Adapters.Sendgrid,
|
||||||
|
api_key: "YOUR_API_KEY"
|
||||||
|
```
|
||||||
|
|
||||||
|
An example for SMTP adapter:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, Pleroma.Emails.Mailer,
|
||||||
|
adapter: Swoosh.Adapters.SMTP,
|
||||||
|
relay: "smtp.gmail.com",
|
||||||
|
username: "YOUR_USERNAME@gmail.com",
|
||||||
|
password: "YOUR_SMTP_PASSWORD",
|
||||||
|
port: 465,
|
||||||
|
ssl: true,
|
||||||
|
tls: :always,
|
||||||
|
auth: :always
|
||||||
|
```
|
||||||
|
|
||||||
|
## :uri_schemes
|
||||||
|
* `valid_schemes`: List of the scheme part that is considered valid to be an URL
|
||||||
|
|
||||||
|
## :instance
|
||||||
|
* `name`: The instance’s name
|
||||||
|
* `email`: Email used to reach an Administrator/Moderator of the instance
|
||||||
|
* `notify_email`: Email used for notifications.
|
||||||
|
* `description`: The instance’s description, can be seen in nodeinfo and ``/api/v1/instance``
|
||||||
|
* `limit`: Posts character limit (CW/Subject included in the counter)
|
||||||
|
* `remote_limit`: Hard character limit beyond which remote posts will be dropped.
|
||||||
|
* `upload_limit`: File size limit of uploads (except for avatar, background, banner)
|
||||||
|
* `avatar_upload_limit`: File size limit of user’s profile avatars
|
||||||
|
* `background_upload_limit`: File size limit of user’s profile backgrounds
|
||||||
|
* `banner_upload_limit`: File size limit of user’s profile banners
|
||||||
|
* `poll_limits`: A map with poll limits for **local** polls
|
||||||
|
* `max_options`: Maximum number of options
|
||||||
|
* `max_option_chars`: Maximum number of characters per option
|
||||||
|
* `min_expiration`: Minimum expiration time (in seconds)
|
||||||
|
* `max_expiration`: Maximum expiration time (in seconds)
|
||||||
|
* `registrations_open`: Enable registrations for anyone, invitations can be enabled when false.
|
||||||
|
* `invites_enabled`: Enable user invitations for admins (depends on `registrations_open: false`).
|
||||||
|
* `account_activation_required`: Require users to confirm their emails before signing in.
|
||||||
|
* `federating`: Enable federation with other instances
|
||||||
|
* `federation_incoming_replies_max_depth`: Max. depth of reply-to activities fetching on incoming federation, to prevent out-of-memory situations while fetching very long threads. If set to `nil`, threads of any depth will be fetched. Lower this value if you experience out-of-memory crashes.
|
||||||
|
* `federation_reachability_timeout_days`: Timeout (in days) of each external federation target being unreachable prior to pausing federating to it.
|
||||||
|
* `allow_relay`: Enable Pleroma’s Relay, which makes it possible to follow a whole instance
|
||||||
|
* `rewrite_policy`: Message Rewrite Policy, either one or a list. Here are the ones available by default:
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.NoOpPolicy`: Doesn’t modify activities (default)
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.DropPolicy`: Drops all activities. It generally doesn’t makes sense to use in production
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.SimplePolicy`: Restrict the visibility of activities from certains instances (See ``:mrf_simple`` section)
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.TagPolicy`: Applies policies to individual users based on tags, which can be set using pleroma-fe/admin-fe/any other app that supports Pleroma Admin API. For example it allows marking posts from individual users nsfw (sensitive)
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.SubchainPolicy`: Selectively runs other MRF policies when messages match (see ``:mrf_subchain`` section)
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.RejectNonPublic`: Drops posts with non-public visibility settings (See ``:mrf_rejectnonpublic`` section)
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.EnsureRePrepended`: Rewrites posts to ensure that replies to posts with subjects do not have an identical subject and instead begin with re:.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy`: Rejects posts from likely spambots by rejecting posts from new users that contain links.
|
||||||
|
* `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (see `:mrf_vocabulary` section)
|
||||||
|
* `public`: Makes the client API in authentificated mode-only except for user-profiles. Useful for disabling the Local Timeline and The Whole Known Network.
|
||||||
|
* `quarantined_instances`: List of ActivityPub instances where private(DMs, followers-only) activities will not be send.
|
||||||
|
* `managed_config`: Whenether the config for pleroma-fe is configured in this config or in ``static/config.json``
|
||||||
|
* `allowed_post_formats`: MIME-type list of formats allowed to be posted (transformed into HTML)
|
||||||
|
* `mrf_transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
|
||||||
|
* `mrf_transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
|
||||||
|
* `scope_copy`: Copy the scope (private/unlisted/public) in replies to posts by default.
|
||||||
|
* `subject_line_behavior`: Allows changing the default behaviour of subject lines in replies. Valid values:
|
||||||
|
* "email": Copy and preprend re:, as in email.
|
||||||
|
* "masto": Copy verbatim, as in Mastodon.
|
||||||
|
* "noop": Don't copy the subject.
|
||||||
|
* `always_show_subject_input`: When set to false, auto-hide the subject field when it's empty.
|
||||||
|
* `extended_nickname_format`: Set to `true` to use extended local nicknames format (allows underscores/dashes). This will break federation with
|
||||||
|
older software for theses nicknames.
|
||||||
|
* `max_pinned_statuses`: The maximum number of pinned statuses. `0` will disable the feature.
|
||||||
|
* `autofollowed_nicknames`: Set to nicknames of (local) users that every new user should automatically follow.
|
||||||
|
* `no_attachment_links`: Set to true to disable automatically adding attachment link text to statuses
|
||||||
|
* `welcome_message`: A message that will be send to a newly registered users as a direct message.
|
||||||
|
* `welcome_user_nickname`: The nickname of the local user that sends the welcome message.
|
||||||
|
* `max_report_comment_size`: The maximum size of the report comment (Default: `1000`)
|
||||||
|
* `safe_dm_mentions`: If set to true, only mentions at the beginning of a post will be used to address people in direct messages. This is to prevent accidental mentioning of people when talking about them (e.g. "@friend hey i really don't like @enemy"). Default: `false`.
|
||||||
|
* `healthcheck`: If set to true, system data will be shown on ``/api/pleroma/healthcheck``.
|
||||||
|
* `remote_post_retention_days`: The default amount of days to retain remote posts when pruning the database.
|
||||||
|
* `skip_thread_containment`: Skip filter out broken threads. The default is `false`.
|
||||||
|
* `limit_to_local_content`: Limit unauthenticated users to search for local statutes and users only. Possible values: `:unauthenticated`, `:all` and `false`. The default is `:unauthenticated`.
|
||||||
|
* `dynamic_configuration`: Allow transferring configuration to DB with the subsequent customization from Admin api.
|
||||||
|
|
||||||
|
|
||||||
|
## :logger
|
||||||
|
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog, and `Quack.Logger` to log to Slack
|
||||||
|
|
||||||
|
An example to enable ONLY ExSyslogger (f/ex in ``prod.secret.exs``) with info and debug suppressed:
|
||||||
|
```elixir
|
||||||
|
config :logger,
|
||||||
|
backends: [{ExSyslogger, :ex_syslogger}]
|
||||||
|
|
||||||
|
config :logger, :ex_syslogger,
|
||||||
|
level: :warn
|
||||||
|
```
|
||||||
|
|
||||||
|
Another example, keeping console output and adding the pid to syslog output:
|
||||||
|
```elixir
|
||||||
|
config :logger,
|
||||||
|
backends: [:console, {ExSyslogger, :ex_syslogger}]
|
||||||
|
|
||||||
|
config :logger, :ex_syslogger,
|
||||||
|
level: :warn,
|
||||||
|
option: [:pid, :ndelay]
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [logger’s documentation](https://hexdocs.pm/logger/Logger.html) and [ex_syslogger’s documentation](https://hexdocs.pm/ex_syslogger/)
|
||||||
|
|
||||||
|
An example of logging info to local syslog, but warn to a Slack channel:
|
||||||
|
```elixir
|
||||||
|
config :logger,
|
||||||
|
backends: [ {ExSyslogger, :ex_syslogger}, Quack.Logger ],
|
||||||
|
level: :info
|
||||||
|
|
||||||
|
config :logger, :ex_syslogger,
|
||||||
|
level: :info,
|
||||||
|
ident: "pleroma",
|
||||||
|
format: "$metadata[$level] $message"
|
||||||
|
|
||||||
|
config :quack,
|
||||||
|
level: :warn,
|
||||||
|
meta: [:all],
|
||||||
|
webhook_url: "https://hooks.slack.com/services/YOUR-API-KEY-HERE"
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Quack Github](https://github.com/azohra/quack) for more details
|
||||||
|
|
||||||
|
## :frontend_configurations
|
||||||
|
|
||||||
|
This can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for `pleroma_fe` and `masto_fe` are configured.
|
||||||
|
|
||||||
|
Frontends can access these settings at `/api/pleroma/frontend_configurations`
|
||||||
|
|
||||||
|
To add your own configuration for PleromaFE, use it like this:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :frontend_configurations,
|
||||||
|
pleroma_fe: %{
|
||||||
|
theme: "pleroma-dark",
|
||||||
|
# ... see /priv/static/static/config.json for the available keys.
|
||||||
|
},
|
||||||
|
masto_fe: %{
|
||||||
|
showInstanceSpecificPanel: true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
These settings **need to be complete**, they will override the defaults.
|
||||||
|
|
||||||
|
NOTE: for versions < 1.0, you need to set [`:fe`](#fe) to false, as shown a few lines below.
|
||||||
|
|
||||||
|
## :fe
|
||||||
|
__THIS IS DEPRECATED__
|
||||||
|
|
||||||
|
If you are using this method, please change it to the [`frontend_configurations`](#frontend_configurations) method.
|
||||||
|
Please **set this option to false** in your config like this:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :fe, false
|
||||||
|
```
|
||||||
|
|
||||||
|
This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:instance`` is set to false.
|
||||||
|
|
||||||
|
* `theme`: Which theme to use, they are defined in ``styles.json``
|
||||||
|
* `logo`: URL of the logo, defaults to Pleroma’s logo
|
||||||
|
* `logo_mask`: Whether to use only the logo's shape as a mask (true) or as a regular image (false)
|
||||||
|
* `logo_margin`: What margin to use around the logo
|
||||||
|
* `background`: URL of the background, unless viewing a user profile with a background that is set
|
||||||
|
* `redirect_root_no_login`: relative URL which indicates where to redirect when a user isn’t logged in.
|
||||||
|
* `redirect_root_login`: relative URL which indicates where to redirect when a user is logged in.
|
||||||
|
* `show_instance_panel`: Whenether to show the instance’s specific panel.
|
||||||
|
* `scope_options_enabled`: Enable setting an notice visibility and subject/CW when posting
|
||||||
|
* `formatting_options_enabled`: Enable setting a formatting different than plain-text (ie. HTML, Markdown) when posting, relates to ``:instance, allowed_post_formats``
|
||||||
|
* `collapse_message_with_subjects`: When a message has a subject(aka Content Warning), collapse it by default
|
||||||
|
* `hide_post_stats`: Hide notices statistics(repeats, favorites, …)
|
||||||
|
* `hide_user_stats`: Hide profile statistics(posts, posts per day, followers, followings, …)
|
||||||
|
|
||||||
|
## :assets
|
||||||
|
|
||||||
|
This section configures assets to be used with various frontends. Currently the only option
|
||||||
|
relates to mascots on the mastodon frontend
|
||||||
|
|
||||||
|
* `mascots`: KeywordList of mascots, each element __MUST__ contain both a `url` and a
|
||||||
|
`mime_type` key.
|
||||||
|
* `default_mascot`: An element from `mascots` - This will be used as the default mascot
|
||||||
|
on MastoFE (default: `:pleroma_fox_tan`)
|
||||||
|
|
||||||
|
## :mrf_simple
|
||||||
|
* `media_removal`: List of instances to remove medias from
|
||||||
|
* `media_nsfw`: List of instances to put medias as NSFW(sensitive) from
|
||||||
|
* `federated_timeline_removal`: List of instances to remove from Federated (aka The Whole Known Network) Timeline
|
||||||
|
* `reject`: List of instances to reject any activities from
|
||||||
|
* `accept`: List of instances to accept any activities from
|
||||||
|
* `report_removal`: List of instances to reject reports from
|
||||||
|
* `avatar_removal`: List of instances to strip avatars from
|
||||||
|
* `banner_removal`: List of instances to strip banners from
|
||||||
|
|
||||||
|
## :mrf_subchain
|
||||||
|
This policy processes messages through an alternate pipeline when a given message matches certain criteria.
|
||||||
|
All criteria are configured as a map of regular expressions to lists of policy modules.
|
||||||
|
|
||||||
|
* `match_actor`: Matches a series of regular expressions against the actor field.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
config :pleroma, :mrf_subchain,
|
||||||
|
match_actor: %{
|
||||||
|
~r/https:\/\/example.com/s => [Pleroma.Web.ActivityPub.MRF.DropPolicy]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## :mrf_rejectnonpublic
|
||||||
|
* `allow_followersonly`: whether to allow followers-only posts
|
||||||
|
* `allow_direct`: whether to allow direct messages
|
||||||
|
|
||||||
|
## :mrf_hellthread
|
||||||
|
* `delist_threshold`: Number of mentioned users after which the message gets delisted (the message can still be seen, but it will not show up in public timelines and mentioned users won't get notifications about it). Set to 0 to disable.
|
||||||
|
* `reject_threshold`: Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.
|
||||||
|
|
||||||
|
## :mrf_keyword
|
||||||
|
* `reject`: A list of patterns which result in message being rejected, each pattern can be a string or a [regular expression](https://hexdocs.pm/elixir/Regex.html)
|
||||||
|
* `federated_timeline_removal`: A list of patterns which result in message being removed from federated timelines (a.k.a unlisted), each pattern can be a string or a [regular expression](https://hexdocs.pm/elixir/Regex.html)
|
||||||
|
* `replace`: A list of tuples containing `{pattern, replacement}`, `pattern` can be a string or a [regular expression](https://hexdocs.pm/elixir/Regex.html)
|
||||||
|
|
||||||
|
## :mrf_vocabulary
|
||||||
|
* `accept`: A list of ActivityStreams terms to accept. If empty, all supported messages are accepted.
|
||||||
|
* `reject`: A list of ActivityStreams terms to reject. If empty, no messages are rejected.
|
||||||
|
|
||||||
|
## :media_proxy
|
||||||
|
* `enabled`: Enables proxying of remote media to the instance’s proxy
|
||||||
|
* `base_url`: The base URL to access a user-uploaded file. Useful when you want to proxy the media files via another host/CDN fronts.
|
||||||
|
* `proxy_opts`: All options defined in `Pleroma.ReverseProxy` documentation, defaults to `[max_body_length: (25*1_048_576)]`.
|
||||||
|
* `whitelist`: List of domains to bypass the mediaproxy
|
||||||
|
|
||||||
|
## :gopher
|
||||||
|
* `enabled`: Enables the gopher interface
|
||||||
|
* `ip`: IP address to bind to
|
||||||
|
* `port`: Port to bind to
|
||||||
|
* `dstport`: Port advertised in urls (optional, defaults to `port`)
|
||||||
|
|
||||||
|
## Pleroma.Web.Endpoint
|
||||||
|
`Phoenix` endpoint configuration, all configuration options can be viewed [here](https://hexdocs.pm/phoenix/Phoenix.Endpoint.html#module-dynamic-configuration), only common options are listed here
|
||||||
|
* `http` - a list containing http protocol configuration, all configuration options can be viewed [here](https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html#module-options), only common options are listed here
|
||||||
|
- `ip` - a tuple consisting of 4 integers
|
||||||
|
- `port`
|
||||||
|
* `url` - a list containing the configuration for generating urls, accepts
|
||||||
|
- `host` - the host without the scheme and a post (e.g `example.com`, not `https://example.com:2020`)
|
||||||
|
- `scheme` - e.g `http`, `https`
|
||||||
|
- `port`
|
||||||
|
- `path`
|
||||||
|
* `extra_cookie_attrs` - a list of `Key=Value` strings to be added as non-standard cookie attributes. Defaults to `["SameSite=Lax"]`. See the [SameSite article](https://www.owasp.org/index.php/SameSite) on OWASP for more info.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Important note**: if you modify anything inside these lists, default `config.exs` values will be overwritten, which may result in breakage, to make sure this does not happen please copy the default value for the list from `config.exs` and modify/add only what you need
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```elixir
|
||||||
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
|
url: [host: "example.com", port: 2020, scheme: "https"],
|
||||||
|
http: [
|
||||||
|
# start copied from config.exs
|
||||||
|
dispatch: [
|
||||||
|
{:_,
|
||||||
|
[
|
||||||
|
{"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
|
||||||
|
{"/websocket", Phoenix.Endpoint.CowboyWebSocket,
|
||||||
|
{Phoenix.Transports.WebSocket,
|
||||||
|
{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, websocket_config}}},
|
||||||
|
{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
|
||||||
|
]}
|
||||||
|
# end copied from config.exs
|
||||||
|
],
|
||||||
|
port: 8080,
|
||||||
|
ip: {127, 0, 0, 1}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
This will make Pleroma listen on `127.0.0.1` port `8080` and generate urls starting with `https://example.com:2020`
|
||||||
|
|
||||||
|
## :activitypub
|
||||||
|
* ``unfollow_blocked``: Whether blocks result in people getting unfollowed
|
||||||
|
* ``outgoing_blocks``: Whether to federate blocks to other instances
|
||||||
|
* ``deny_follow_blocked``: Whether to disallow following an account that has blocked the user in question
|
||||||
|
|
||||||
|
## :http_security
|
||||||
|
* ``enabled``: Whether the managed content security policy is enabled
|
||||||
|
* ``sts``: Whether to additionally send a `Strict-Transport-Security` header
|
||||||
|
* ``sts_max_age``: The maximum age for the `Strict-Transport-Security` header if sent
|
||||||
|
* ``ct_max_age``: The maximum age for the `Expect-CT` header if sent
|
||||||
|
* ``referrer_policy``: The referrer policy to use, either `"same-origin"` or `"no-referrer"`
|
||||||
|
* ``report_uri``: Adds the specified url to `report-uri` and `report-to` group in CSP header.
|
||||||
|
|
||||||
|
## :mrf_user_allowlist
|
||||||
|
|
||||||
|
The keys in this section are the domain names that the policy should apply to.
|
||||||
|
Each key should be assigned a list of users that should be allowed through by
|
||||||
|
their ActivityPub ID.
|
||||||
|
|
||||||
|
An example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :mrf_user_allowlist,
|
||||||
|
"example.org": ["https://example.org/users/admin"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## :web_push_encryption, :vapid_details
|
||||||
|
|
||||||
|
Web Push Notifications configuration. You can use the mix task `mix web_push.gen.keypair` to generate it.
|
||||||
|
|
||||||
|
* ``subject``: a mailto link for the administrative contact. It’s best if this email is not a personal email address, but rather a group email so that if a person leaves an organization, is unavailable for an extended period, or otherwise can’t respond, someone else on the list can.
|
||||||
|
* ``public_key``: VAPID public key
|
||||||
|
* ``private_key``: VAPID private key
|
||||||
|
|
||||||
|
## Pleroma.Captcha
|
||||||
|
* `enabled`: Whether the captcha should be shown on registration
|
||||||
|
* `method`: The method/service to use for captcha
|
||||||
|
* `seconds_valid`: The time in seconds for which the captcha is valid
|
||||||
|
|
||||||
|
### Pleroma.Captcha.Kocaptcha
|
||||||
|
Kocaptcha is a very simple captcha service with a single API endpoint,
|
||||||
|
the source code is here: https://github.com/koto-bank/kocaptcha. The default endpoint
|
||||||
|
`https://captcha.kotobank.ch` is hosted by the developer.
|
||||||
|
|
||||||
|
* `endpoint`: the kocaptcha endpoint to use
|
||||||
|
|
||||||
|
## :admin_token
|
||||||
|
|
||||||
|
Allows to set a token that can be used to authenticate with the admin api without using an actual user by giving it as the 'admin_token' parameter. Example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :admin_token, "somerandomtoken"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can then do
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl "http://localhost:4000/api/pleroma/admin/invite_token?admin_token=somerandomtoken"
|
||||||
|
```
|
||||||
|
|
||||||
|
## :pleroma_job_queue
|
||||||
|
|
||||||
|
[Pleroma Job Queue](https://git.pleroma.social/pleroma/pleroma_job_queue) configuration: a list of queues with maximum concurrent jobs.
|
||||||
|
|
||||||
|
Pleroma has the following queues:
|
||||||
|
|
||||||
|
* `federator_outgoing` - Outgoing federation
|
||||||
|
* `federator_incoming` - Incoming federation
|
||||||
|
* `mailer` - Email sender, see [`Pleroma.Emails.Mailer`](#pleroma-emails-mailer)
|
||||||
|
* `transmogrifier` - Transmogrifier
|
||||||
|
* `web_push` - Web push notifications
|
||||||
|
* `scheduled_activities` - Scheduled activities, see [`Pleroma.ScheduledActivities`](#pleromascheduledactivity)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma_job_queue, :queues,
|
||||||
|
federator_incoming: 50,
|
||||||
|
federator_outgoing: 50
|
||||||
|
```
|
||||||
|
|
||||||
|
This config contains two queues: `federator_incoming` and `federator_outgoing`. Both have the `max_jobs` set to `50`.
|
||||||
|
|
||||||
|
## Pleroma.Web.Federator.RetryQueue
|
||||||
|
|
||||||
|
* `enabled`: If set to `true`, failed federation jobs will be retried
|
||||||
|
* `max_jobs`: The maximum amount of parallel federation jobs running at the same time.
|
||||||
|
* `initial_timeout`: The initial timeout in seconds
|
||||||
|
* `max_retries`: The maximum number of times a federation job is retried
|
||||||
|
|
||||||
|
## Pleroma.Web.Metadata
|
||||||
|
* `providers`: a list of metadata providers to enable. Providers available:
|
||||||
|
* Pleroma.Web.Metadata.Providers.OpenGraph
|
||||||
|
* Pleroma.Web.Metadata.Providers.TwitterCard
|
||||||
|
* Pleroma.Web.Metadata.Providers.RelMe - add links from user bio with rel=me into the `<header>` as `<link rel=me>`
|
||||||
|
* `unfurl_nsfw`: If set to `true` nsfw attachments will be shown in previews
|
||||||
|
|
||||||
|
## :rich_media
|
||||||
|
* `enabled`: if enabled the instance will parse metadata from attached links to generate link previews
|
||||||
|
* `ignore_hosts`: list of hosts which will be ignored by the metadata parser. For example `["accounts.google.com", "xss.website"]`, defaults to `[]`.
|
||||||
|
* `ignore_tld`: list TLDs (top-level domains) which will ignore for parse metadata. default is ["local", "localdomain", "lan"]
|
||||||
|
|
||||||
|
## :fetch_initial_posts
|
||||||
|
* `enabled`: if enabled, when a new user is federated with, fetch some of their latest posts
|
||||||
|
* `pages`: the amount of pages to fetch
|
||||||
|
|
||||||
|
## :hackney_pools
|
||||||
|
|
||||||
|
Advanced. Tweaks Hackney (http client) connections pools.
|
||||||
|
|
||||||
|
There's three pools used:
|
||||||
|
|
||||||
|
* `:federation` for the federation jobs.
|
||||||
|
You may want this pool max_connections to be at least equal to the number of federator jobs + retry queue jobs.
|
||||||
|
* `:media` for rich media, media proxy
|
||||||
|
* `:upload` for uploaded media (if using a remote uploader and `proxy_remote: true`)
|
||||||
|
|
||||||
|
For each pool, the options are:
|
||||||
|
|
||||||
|
* `max_connections` - how much connections a pool can hold
|
||||||
|
* `timeout` - retention duration for connections
|
||||||
|
|
||||||
|
## :auto_linker
|
||||||
|
|
||||||
|
Configuration for the `auto_linker` library:
|
||||||
|
|
||||||
|
* `class: "auto-linker"` - specify the class to be added to the generated link. false to clear
|
||||||
|
* `rel: "noopener noreferrer"` - override the rel attribute. false to clear
|
||||||
|
* `new_window: true` - set to false to remove `target='_blank'` attribute
|
||||||
|
* `scheme: false` - Set to true to link urls with schema `http://google.com`
|
||||||
|
* `truncate: false` - Set to a number to truncate urls longer then the number. Truncated urls will end in `..`
|
||||||
|
* `strip_prefix: true` - Strip the scheme prefix
|
||||||
|
* `extra: false` - link urls with rarely used schemes (magnet, ipfs, irc, etc.)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :auto_linker,
|
||||||
|
opts: [
|
||||||
|
scheme: true,
|
||||||
|
extra: true,
|
||||||
|
class: false,
|
||||||
|
strip_prefix: false,
|
||||||
|
new_window: false,
|
||||||
|
rel: false
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pleroma.ScheduledActivity
|
||||||
|
|
||||||
|
* `daily_user_limit`: the number of scheduled activities a user is allowed to create in a single day (Default: `25`)
|
||||||
|
* `total_user_limit`: the number of scheduled activities a user is allowed to create in total (Default: `300`)
|
||||||
|
* `enabled`: whether scheduled activities are sent to the job queue to be executed
|
||||||
|
|
||||||
|
## Pleroma.Web.Auth.Authenticator
|
||||||
|
|
||||||
|
* `Pleroma.Web.Auth.PleromaAuthenticator`: default database authenticator
|
||||||
|
* `Pleroma.Web.Auth.LDAPAuthenticator`: LDAP authentication
|
||||||
|
|
||||||
|
## :ldap
|
||||||
|
|
||||||
|
Use LDAP for user authentication. When a user logs in to the Pleroma
|
||||||
|
instance, the name and password will be verified by trying to authenticate
|
||||||
|
(bind) to an LDAP server. If a user exists in the LDAP directory but there
|
||||||
|
is no account with the same name yet on the Pleroma instance then a new
|
||||||
|
Pleroma account will be created with the same name as the LDAP user name.
|
||||||
|
|
||||||
|
* `enabled`: enables LDAP authentication
|
||||||
|
* `host`: LDAP server hostname
|
||||||
|
* `port`: LDAP port, e.g. 389 or 636
|
||||||
|
* `ssl`: true to use SSL, usually implies the port 636
|
||||||
|
* `sslopts`: additional SSL options
|
||||||
|
* `tls`: true to start TLS, usually implies the port 389
|
||||||
|
* `tlsopts`: additional TLS options
|
||||||
|
* `base`: LDAP base, e.g. "dc=example,dc=com"
|
||||||
|
* `uid`: LDAP attribute name to authenticate the user, e.g. when "cn", the filter will be "cn=username,base"
|
||||||
|
|
||||||
|
## BBS / SSH access
|
||||||
|
|
||||||
|
To enable simple command line interface accessible over ssh, add a setting like this to your configuration file:
|
||||||
|
|
||||||
|
```exs
|
||||||
|
app_dir = File.cwd!
|
||||||
|
priv_dir = Path.join([app_dir, "priv/ssh_keys"])
|
||||||
|
|
||||||
|
config :esshd,
|
||||||
|
enabled: true,
|
||||||
|
priv_dir: priv_dir,
|
||||||
|
handler: "Pleroma.BBS.Handler",
|
||||||
|
port: 10_022,
|
||||||
|
password_authenticator: "Pleroma.BBS.Authenticator"
|
||||||
|
```
|
||||||
|
|
||||||
|
Feel free to adjust the priv_dir and port number. Then you will have to create the key for the keys (in the example `priv/ssh_keys`) and create the host keys with `ssh-keygen -m PEM -N "" -b 2048 -t rsa -f ssh_host_rsa_key`. After restarting, you should be able to connect to your Pleroma instance with `ssh username@server -p $PORT`
|
||||||
|
|
||||||
|
## :auth
|
||||||
|
|
||||||
|
* `Pleroma.Web.Auth.PleromaAuthenticator`: default database authenticator
|
||||||
|
* `Pleroma.Web.Auth.LDAPAuthenticator`: LDAP authentication
|
||||||
|
|
||||||
|
Authentication / authorization settings.
|
||||||
|
|
||||||
|
* `auth_template`: authentication form template. By default it's `show.html` which corresponds to `lib/pleroma/web/templates/o_auth/o_auth/show.html.eex`.
|
||||||
|
* `oauth_consumer_template`: OAuth consumer mode authentication form template. By default it's `consumer.html` which corresponds to `lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex`.
|
||||||
|
* `oauth_consumer_strategies`: the list of enabled OAuth consumer strategies; by default it's set by `OAUTH_CONSUMER_STRATEGIES` environment variable. Each entry in this space-delimited string should be of format `<strategy>` or `<strategy>:<dependency>` (e.g. `twitter` or `keycloak:ueberauth_keycloak_strategy` in case dependency is named differently than `ueberauth_<strategy>`).
|
||||||
|
|
||||||
|
## OAuth consumer mode
|
||||||
|
|
||||||
|
OAuth consumer mode allows sign in / sign up via external OAuth providers (e.g. Twitter, Facebook, Google, Microsoft, etc.).
|
||||||
|
Implementation is based on Ueberauth; see the list of [available strategies](https://github.com/ueberauth/ueberauth/wiki/List-of-Strategies).
|
||||||
|
|
||||||
|
Note: each strategy is shipped as a separate dependency; in order to get the strategies, run `OAUTH_CONSUMER_STRATEGIES="..." mix deps.get`,
|
||||||
|
e.g. `OAUTH_CONSUMER_STRATEGIES="twitter facebook google microsoft" mix deps.get`.
|
||||||
|
The server should also be started with `OAUTH_CONSUMER_STRATEGIES="..." mix phx.server` in case you enable any strategies.
|
||||||
|
|
||||||
|
Note: each strategy requires separate setup (on external provider side and Pleroma side). Below are the guidelines on setting up most popular strategies.
|
||||||
|
|
||||||
|
Note: make sure that `"SameSite=Lax"` is set in `extra_cookie_attrs` when you have this feature enabled. OAuth consumer mode will not work with `"SameSite=Strict"`
|
||||||
|
|
||||||
|
* For Twitter, [register an app](https://developer.twitter.com/en/apps), configure callback URL to https://<your_host>/oauth/twitter/callback
|
||||||
|
|
||||||
|
* For Facebook, [register an app](https://developers.facebook.com/apps), configure callback URL to https://<your_host>/oauth/facebook/callback, enable Facebook Login service at https://developers.facebook.com/apps/<app_id>/fb-login/settings/
|
||||||
|
|
||||||
|
* For Google, [register an app](https://console.developers.google.com), configure callback URL to https://<your_host>/oauth/google/callback
|
||||||
|
|
||||||
|
* For Microsoft, [register an app](https://portal.azure.com), configure callback URL to https://<your_host>/oauth/microsoft/callback
|
||||||
|
|
||||||
|
Once the app is configured on external OAuth provider side, add app's credentials and strategy-specific settings (if any — e.g. see Microsoft below) to `config/prod.secret.exs`,
|
||||||
|
per strategy's documentation (e.g. [ueberauth_twitter](https://github.com/ueberauth/ueberauth_twitter)). Example config basing on environment variables:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# Twitter
|
||||||
|
config :ueberauth, Ueberauth.Strategy.Twitter.OAuth,
|
||||||
|
consumer_key: System.get_env("TWITTER_CONSUMER_KEY"),
|
||||||
|
consumer_secret: System.get_env("TWITTER_CONSUMER_SECRET")
|
||||||
|
|
||||||
|
# Facebook
|
||||||
|
config :ueberauth, Ueberauth.Strategy.Facebook.OAuth,
|
||||||
|
client_id: System.get_env("FACEBOOK_APP_ID"),
|
||||||
|
client_secret: System.get_env("FACEBOOK_APP_SECRET"),
|
||||||
|
redirect_uri: System.get_env("FACEBOOK_REDIRECT_URI")
|
||||||
|
|
||||||
|
# Google
|
||||||
|
config :ueberauth, Ueberauth.Strategy.Google.OAuth,
|
||||||
|
client_id: System.get_env("GOOGLE_CLIENT_ID"),
|
||||||
|
client_secret: System.get_env("GOOGLE_CLIENT_SECRET"),
|
||||||
|
redirect_uri: System.get_env("GOOGLE_REDIRECT_URI")
|
||||||
|
|
||||||
|
# Microsoft
|
||||||
|
config :ueberauth, Ueberauth.Strategy.Microsoft.OAuth,
|
||||||
|
client_id: System.get_env("MICROSOFT_CLIENT_ID"),
|
||||||
|
client_secret: System.get_env("MICROSOFT_CLIENT_SECRET")
|
||||||
|
|
||||||
|
config :ueberauth, Ueberauth,
|
||||||
|
providers: [
|
||||||
|
microsoft: {Ueberauth.Strategy.Microsoft, [callback_params: []]}
|
||||||
|
]
|
||||||
|
|
||||||
|
# Keycloak
|
||||||
|
# Note: make sure to add `keycloak:ueberauth_keycloak_strategy` entry to `OAUTH_CONSUMER_STRATEGIES` environment variable
|
||||||
|
keycloak_url = "https://publicly-reachable-keycloak-instance.org:8080"
|
||||||
|
|
||||||
|
config :ueberauth, Ueberauth.Strategy.Keycloak.OAuth,
|
||||||
|
client_id: System.get_env("KEYCLOAK_CLIENT_ID"),
|
||||||
|
client_secret: System.get_env("KEYCLOAK_CLIENT_SECRET"),
|
||||||
|
site: keycloak_url,
|
||||||
|
authorize_url: "#{keycloak_url}/auth/realms/master/protocol/openid-connect/auth",
|
||||||
|
token_url: "#{keycloak_url}/auth/realms/master/protocol/openid-connect/token",
|
||||||
|
userinfo_url: "#{keycloak_url}/auth/realms/master/protocol/openid-connect/userinfo",
|
||||||
|
token_method: :post
|
||||||
|
|
||||||
|
config :ueberauth, Ueberauth,
|
||||||
|
providers: [
|
||||||
|
keycloak: {Ueberauth.Strategy.Keycloak, [uid_field: :email]}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## OAuth 2.0 provider - :oauth2
|
||||||
|
|
||||||
|
Configure OAuth 2 provider capabilities:
|
||||||
|
|
||||||
|
* `token_expires_in` - The lifetime in seconds of the access token.
|
||||||
|
* `issue_new_refresh_token` - Keeps old refresh token or generate new refresh token when to obtain an access token.
|
||||||
|
* `clean_expired_tokens` - Enable a background job to clean expired oauth tokens. Defaults to `false`.
|
||||||
|
* `clean_expired_tokens_interval` - Interval to run the job to clean expired tokens. Defaults to `86_400_000` (24 hours).
|
||||||
|
|
||||||
|
## :emoji
|
||||||
|
* `shortcode_globs`: Location of custom emoji files. `*` can be used as a wildcard. Example `["/emoji/custom/**/*.png"]`
|
||||||
|
* `pack_extensions`: A list of file extensions for emojis, when no emoji.txt for a pack is present. Example `[".png", ".gif"]`
|
||||||
|
* `groups`: Emojis are ordered in groups (tags). This is an array of key-value pairs where the key is the groupname and the value the location or array of locations. `*` can be used as a wildcard. Example `[Custom: ["/emoji/*.png", "/emoji/custom/*.png"]]`
|
||||||
|
* `default_manifest`: Location of the JSON-manifest. This manifest contains information about the emoji-packs you can download. Currently only one manifest can be added (no arrays).
|
||||||
|
|
||||||
|
## Database options
|
||||||
|
|
||||||
|
### RUM indexing for full text search
|
||||||
|
* `rum_enabled`: If RUM indexes should be used. Defaults to `false`.
|
||||||
|
|
||||||
|
RUM indexes are an alternative indexing scheme that is not included in PostgreSQL by default. While they may eventually be mainlined, for now they have to be installed as a PostgreSQL extension from https://github.com/postgrespro/rum.
|
||||||
|
|
||||||
|
Their advantage over the standard GIN indexes is that they allow efficient ordering of search results by timestamp, which makes search queries a lot faster on larger servers, by one or two orders of magnitude. They take up around 3 times as much space as GIN indexes.
|
||||||
|
|
||||||
|
To enable them, both the `rum_enabled` flag has to be set and the following special migration has to be run:
|
||||||
|
|
||||||
|
`mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`
|
||||||
|
|
||||||
|
This will probably take a long time.
|
||||||
|
|
||||||
|
## :rate_limit
|
||||||
|
|
||||||
|
A keyword list of rate limiters where a key is a limiter name and value is the limiter configuration. The basic configuration is a tuple where:
|
||||||
|
|
||||||
|
* The first element: `scale` (Integer). The time scale in milliseconds.
|
||||||
|
* The second element: `limit` (Integer). How many requests to limit in the time scale provided.
|
||||||
|
|
||||||
|
It is also possible to have different limits for unauthenticated and authenticated users: the keyword value must be a list of two tuples where the first one is a config for unauthenticated users and the second one is for authenticated.
|
||||||
|
|
||||||
|
See [`Pleroma.Plugs.RateLimiter`](Pleroma.Plugs.RateLimiter.html) documentation for examples.
|
|
@ -0,0 +1,17 @@
|
||||||
|
# General tips for customizing Pleroma FE
|
||||||
|
There are some configuration scripts for Pleroma BE and FE:
|
||||||
|
|
||||||
|
1. `config/prod.secret.exs`
|
||||||
|
1. `config/config.exs`
|
||||||
|
1. `priv/static/static/config.json`
|
||||||
|
|
||||||
|
The `prod.secret.exs` affects first. `config.exs` is for fallback or default. `config.json` is for GNU-social-BE-Pleroma-FE instances.
|
||||||
|
|
||||||
|
Usually all you have to do is:
|
||||||
|
|
||||||
|
1. Copy the section in the `config/config.exs` which you want to activate.
|
||||||
|
1. Paste into `config/prod.secret.exs`.
|
||||||
|
1. Edit `config/prod.secret.exs`.
|
||||||
|
1. Restart the Pleroma daemon.
|
||||||
|
|
||||||
|
`prod.secret.exs` is for the `MIX_ENV=prod` environment. `dev.secret.exs` is for the `MIX_ENV=dev` environment respectively.
|
|
@ -4,7 +4,6 @@ Before you add your own custom emoji, check if they are available in an existing
|
||||||
See `Mix.Tasks.Pleroma.Emoji` for information about emoji packs.
|
See `Mix.Tasks.Pleroma.Emoji` for information about emoji packs.
|
||||||
|
|
||||||
To add custom emoji:
|
To add custom emoji:
|
||||||
|
|
||||||
* Create the `STATIC-DIR/emoji/` directory if it doesn't exist
|
* Create the `STATIC-DIR/emoji/` directory if it doesn't exist
|
||||||
(`STATIC-DIR` is configurable, `instance/static/` by default)
|
(`STATIC-DIR` is configurable, `instance/static/` by default)
|
||||||
* Create a directory with whatever name you want (custom is a good name to show the purpose of it).
|
* Create a directory with whatever name you want (custom is a good name to show the purpose of it).
|
|
@ -36,7 +36,7 @@ content-security-policy:
|
||||||
default-src 'none';
|
default-src 'none';
|
||||||
base-uri 'self';
|
base-uri 'self';
|
||||||
frame-ancestors 'none';
|
frame-ancestors 'none';
|
||||||
img-src 'self' data: blob: https:;
|
img-src 'self' data: https:;
|
||||||
media-src 'self' https:;
|
media-src 'self' https:;
|
||||||
style-src 'self' 'unsafe-inline';
|
style-src 'self' 'unsafe-inline';
|
||||||
font-src 'self';
|
font-src 'self';
|
|
@ -0,0 +1,32 @@
|
||||||
|
# How to activate mediaproxy
|
||||||
|
## Explanation
|
||||||
|
|
||||||
|
Without the `mediaproxy` function, Pleroma don't store any remote content like pictures, video etc. locally. So every time you open Pleroma, the content is loaded from the source server, from where the post is coming. This can result in slowly loading content or/and increased bandwidth usage on the source server.
|
||||||
|
With the `mediaproxy` function you can use the cache ability of nginx, to cache these content, so user can access it faster, cause it's loaded from your server.
|
||||||
|
|
||||||
|
## Activate it
|
||||||
|
|
||||||
|
* Edit your nginx config and add the following location:
|
||||||
|
```
|
||||||
|
location /proxy {
|
||||||
|
proxy_cache pleroma_media_cache;
|
||||||
|
proxy_cache_lock on;
|
||||||
|
proxy_pass http://localhost:4000;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Also add the following on top of the configuration, outside of the `server` block:
|
||||||
|
```
|
||||||
|
proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off;
|
||||||
|
```
|
||||||
|
If you came here from one of the installation guides, take a look at the example configuration `/installation/pleroma.nginx`, where this part is already included.
|
||||||
|
|
||||||
|
* Append the following to your `prod.secret.exs` or `dev.secret.exs` (depends on which mode your instance is running):
|
||||||
|
```
|
||||||
|
config :pleroma, :media_proxy,
|
||||||
|
enabled: true,
|
||||||
|
redirect_on_failure: true
|
||||||
|
#base_url: "https://cache.pleroma.social"
|
||||||
|
```
|
||||||
|
If you want to use a subdomain to serve the files, uncomment `base_url`, change the url and add a comma after `true` in the previous line.
|
||||||
|
|
||||||
|
* Restart nginx and Pleroma
|
|
@ -0,0 +1,31 @@
|
||||||
|
# How to activate user recommendation (Who to follow panel)
|
||||||
|
![who-to-follow-panel-small](/uploads/9de1b1300436c32461d272945f1bc23e/who-to-follow-panel-small.png)
|
||||||
|
|
||||||
|
To show the *who to follow* panel, edit `config/prod.secret.exs` in the Pleroma backend. Following code activates the *who to follow* panel:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :suggestions,
|
||||||
|
enabled: true,
|
||||||
|
third_party_engine:
|
||||||
|
"http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-suggestions-api.cgi?{{host}}+{{user}}",
|
||||||
|
timeout: 300_000,
|
||||||
|
limit: 40,
|
||||||
|
web: "https://vinayaka.distsn.org"
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
`config/config.exs` already includes this code, but `enabled:` is `false`.
|
||||||
|
|
||||||
|
`/api/v1/suggestions` is also provided when *who to follow* panel is enabled.
|
||||||
|
|
||||||
|
For advanced customization, following code shows the newcomers of the fediverse at the *who to follow* panel:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :pleroma, :suggestions,
|
||||||
|
enabled: true,
|
||||||
|
third_party_engine:
|
||||||
|
"http://vinayaka.distsn.org/cgi-bin/vinayaka-user-new-suggestions-api.cgi?{{host}}+{{user}}",
|
||||||
|
timeout: 60_000,
|
||||||
|
limit: 40,
|
||||||
|
web: "https://vinayaka.distsn.org/user-new.html"
|
||||||
|
```
|
|
@ -123,7 +123,7 @@ In addition to that, replace the existing nginx config's contents with the examp
|
||||||
|
|
||||||
If not an I2P-only instance, add the nginx config below to your existing config at `/etc/nginx/sites-enabled/pleroma.nginx`.
|
If not an I2P-only instance, add the nginx config below to your existing config at `/etc/nginx/sites-enabled/pleroma.nginx`.
|
||||||
|
|
||||||
And for both cases, disable CSP in Pleroma's config (STS is disabled by default) so you can define those yourself separately from the clearnet (if your instance is also on the clearnet).
|
And for both cases, disable CSP in Pleroma's config (STS is disabled by default) so you can define those yourself seperately from the clearnet (if your instance is also on the clearnet).
|
||||||
Copy the following into the `config/prod.secret.exs` in your Pleroma folder (/home/pleroma/pleroma/):
|
Copy the following into the `config/prod.secret.exs` in your Pleroma folder (/home/pleroma/pleroma/):
|
||||||
```
|
```
|
||||||
config :pleroma, :http_security,
|
config :pleroma, :http_security,
|
|
@ -0,0 +1,122 @@
|
||||||
|
# Message Rewrite Facility
|
||||||
|
The Message Rewrite Facility (MRF) is a subsystem that is implemented as a series of hooks that allows the administrator to rewrite or discard messages.
|
||||||
|
|
||||||
|
Possible uses include:
|
||||||
|
|
||||||
|
* marking incoming messages with media from a given account or instance as sensitive
|
||||||
|
* rejecting messages from a specific instance
|
||||||
|
* rejecting reports (flags) from a specific instance
|
||||||
|
* removing/unlisting messages from the public timelines
|
||||||
|
* removing media from messages
|
||||||
|
* sending only public messages to a specific instance
|
||||||
|
|
||||||
|
The MRF provides user-configurable policies. The default policy is `NoOpPolicy`, which disables the MRF functionality. Pleroma also includes an easy to use policy called `SimplePolicy` which maps messages matching certain pre-defined criterion to actions built into the policy module.
|
||||||
|
It is possible to use multiple, active MRF policies at the same time.
|
||||||
|
|
||||||
|
## Quarantine Instances
|
||||||
|
|
||||||
|
You have the ability to prevent from private / followers-only messages from federating with specific instances. Which means they will only get the public or unlisted messages from your instance.
|
||||||
|
|
||||||
|
If, for example, you're using `MIX_ENV=prod` aka using production mode, you would open your configuration file located in `config/prod.secret.exs` and edit or add the option under your `:instance` config object. Then you would specify the instance within quotes.
|
||||||
|
```
|
||||||
|
config :pleroma, :instance,
|
||||||
|
[...]
|
||||||
|
quarantined_instances: ["instance.example", "other.example"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using `SimplePolicy`
|
||||||
|
|
||||||
|
`SimplePolicy` is capable of handling most common admin tasks.
|
||||||
|
|
||||||
|
To use `SimplePolicy`, you must enable it. Do so by adding the following to your `:instance` config object, so that it looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
config :pleroma, :instance,
|
||||||
|
[...]
|
||||||
|
rewrite_policy: Pleroma.Web.ActivityPub.MRF.SimplePolicy
|
||||||
|
```
|
||||||
|
|
||||||
|
Once `SimplePolicy` is enabled, you can configure various groups in the `:mrf_simple` config object. These groups are:
|
||||||
|
|
||||||
|
* `media_removal`: Servers in this group will have media stripped from incoming messages.
|
||||||
|
* `media_nsfw`: Servers in this group will have the #nsfw tag and sensitive setting injected into incoming messages which contain media.
|
||||||
|
* `reject`: Servers in this group will have their messages rejected.
|
||||||
|
* `federated_timeline_removal`: Servers in this group will have their messages unlisted from the public timelines by flipping the `to` and `cc` fields.
|
||||||
|
* `report_removal`: Servers in this group will have their reports (flags) rejected.
|
||||||
|
|
||||||
|
Servers should be configured as lists.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
This example will enable `SimplePolicy`, block media from `illegalporn.biz`, mark media as NSFW from `porn.biz` and `porn.business`, reject messages from `spam.com`, remove messages from `spam.university` from the federated timeline and block reports (flags) from `whiny.whiner`:
|
||||||
|
|
||||||
|
```
|
||||||
|
config :pleroma, :instance,
|
||||||
|
rewrite_policy: [Pleroma.Web.ActivityPub.MRF.SimplePolicy]
|
||||||
|
|
||||||
|
config :pleroma, :mrf_simple,
|
||||||
|
media_removal: ["illegalporn.biz"],
|
||||||
|
media_nsfw: ["porn.biz", "porn.business"],
|
||||||
|
reject: ["spam.com"],
|
||||||
|
federated_timeline_removal: ["spam.university"],
|
||||||
|
report_removal: ["whiny.whiner"]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use with Care
|
||||||
|
|
||||||
|
The effects of MRF policies can be very drastic. It is important to use this functionality carefully. Always try to talk to an admin before writing an MRF policy concerning their instance.
|
||||||
|
|
||||||
|
## Writing your own MRF Policy
|
||||||
|
|
||||||
|
As discussed above, the MRF system is a modular system that supports pluggable policies. This means that an admin may write a custom MRF policy in Elixir or any other language that runs on the Erlang VM, by specifying the module name in the `rewrite_policy` config setting.
|
||||||
|
|
||||||
|
For example, here is a sample policy module which rewrites all messages to "new message content":
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# This is a sample MRF policy which rewrites all Notes to have "new message
|
||||||
|
# content."
|
||||||
|
defmodule Site.RewritePolicy do
|
||||||
|
@behavior Pleroma.Web.ActivityPub.MRF
|
||||||
|
|
||||||
|
# Catch messages which contain Note objects with actual data to filter.
|
||||||
|
# Capture the object as `object`, the message content as `content` and the
|
||||||
|
# message itself as `message`.
|
||||||
|
@impl true
|
||||||
|
def filter(%{"type" => Create", "object" => {"type" => "Note", "content" => content} = object} = message)
|
||||||
|
when is_binary(content) do
|
||||||
|
# Subject / CW is stored as summary instead of `name` like other AS2 objects
|
||||||
|
# because of Mastodon doing it that way.
|
||||||
|
summary = object["summary"]
|
||||||
|
|
||||||
|
# Message edits go here.
|
||||||
|
content = "new message content"
|
||||||
|
|
||||||
|
# Assemble the mutated object.
|
||||||
|
object =
|
||||||
|
object
|
||||||
|
|> Map.put("content", content)
|
||||||
|
|> Map.put("summary", summary)
|
||||||
|
|
||||||
|
# Assemble the mutated message.
|
||||||
|
message = Map.put(message, "object", object)
|
||||||
|
{:ok, message}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Let all other messages through without modifying them.
|
||||||
|
@impl true
|
||||||
|
def filter(message), do: {:ok, message}
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
If you save this file as `lib/site/mrf/rewrite_policy.ex`, it will be included when you next rebuild Pleroma. You can enable it in the configuration like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
config :pleroma, :instance,
|
||||||
|
rewrite_policy: [
|
||||||
|
Pleroma.Web.ActivityPub.MRF.SimplePolicy,
|
||||||
|
Site.RewritePolicy
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that the Pleroma developers consider custom MRF policy modules to fall under the purview of the AGPL. As such, you are obligated to release the sources to your custom MRF policy modules upon request.
|
|
@ -75,7 +75,7 @@ If not a Tor-only instance,
|
||||||
add the nginx config below to your existing config at `/etc/nginx/sites-enabled/pleroma.nginx`.
|
add the nginx config below to your existing config at `/etc/nginx/sites-enabled/pleroma.nginx`.
|
||||||
|
|
||||||
---
|
---
|
||||||
For both cases, disable CSP in Pleroma's config (STS is disabled by default) so you can define those yourself separately from the clearnet (if your instance is also on the clearnet).
|
For both cases, disable CSP in Pleroma's config (STS is disabled by default) so you can define those yourself seperately from the clearnet (if your instance is also on the clearnet).
|
||||||
Copy the following into the `config/prod.secret.exs` in your Pleroma folder (/home/pleroma/pleroma/):
|
Copy the following into the `config/prod.secret.exs` in your Pleroma folder (/home/pleroma/pleroma/):
|
||||||
```
|
```
|
||||||
config :pleroma, :http_security,
|
config :pleroma, :http_security,
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Small customizations
|
||||||
|
Replace `dev.secret.exs` with `prod.secret.exs` according to your setup.
|
||||||
|
|
||||||
|
# Thumbnail
|
||||||
|
|
||||||
|
Replace `priv/static/instance/thumbnail.jpeg` with your selfie or other neat picture. It will appear in [Pleroma Instances](http://distsn.org/pleroma-instances.html).
|
||||||
|
|
||||||
|
# Instance-specific panel
|
||||||
|
|
||||||
|
![instance-specific panel demo](/uploads/296b19ec806b130e0b49b16bfe29ce8a/image.png)
|
||||||
|
|
||||||
|
To show the instance specific panel, set `show_instance_panel` to `true` in `config/dev.secret.exs`. You can modify its content by editing `priv/static/instance/panel.html`.
|
||||||
|
|
||||||
|
# Background
|
||||||
|
|
||||||
|
You can change the background of your Pleroma instance by uploading it to `priv/static/static`, and then changing `"background"` in `config/dev.secret.exs` accordingly.
|
||||||
|
|
||||||
|
# Logo
|
||||||
|
|
||||||
|
![logo modification demo](/uploads/c70b14de60fa74245e7f0dcfa695ebff/image.png)
|
||||||
|
|
||||||
|
If you want to give a brand to your instance, look no further. You can change the logo of your instance by uploading it to `priv/static/static`, and then changing `logo` in `config/dev.secret.exs` accordingly.
|
||||||
|
|
||||||
|
# Theme
|
||||||
|
|
||||||
|
All users of your instance will be able to change the theme they use by going to the settings (the cog in the top-right hand corner). However, if you wish to change the default theme, you can do so by editing `theme` in `config/dev.secret.exs` accordingly.
|
||||||
|
|
||||||
|
# Terms of Service
|
||||||
|
|
||||||
|
Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by changing `priv/static/static/terms-of-service.html`.
|
||||||
|
|
||||||
|
# Message Visibility
|
||||||
|
|
||||||
|
To enable message visibility options when posting like in the Mastodon frontend, set
|
||||||
|
`scope_options_enabled` to `true` in `config/dev.secret.exs`.
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Static Directory
|
||||||
|
|
||||||
|
Static frontend files are shipped in `priv/static/` and tracked by version control in this repository. If you want to overwrite or update these without the possibility of merge conflicts, you can write your custom versions to `instance/static/`.
|
||||||
|
|
||||||
|
```
|
||||||
|
config :pleroma, :instance,
|
||||||
|
static_dir: "instance/static/",
|
||||||
|
```
|
||||||
|
|
||||||
|
You can overwrite this value in your configuration to use a different static instance directory.
|
||||||
|
|
||||||
|
## robots.txt
|
||||||
|
|
||||||
|
By default, the `robots.txt` that ships in `priv/static/` is permissive. It allows well-behaved search engines to index all of your instance's URIs.
|
||||||
|
|
||||||
|
If you want to generate a restrictive `robots.txt`, you can run the following mix task. The generated `robots.txt` will be written in your instance static directory.
|
||||||
|
|
||||||
|
```
|
||||||
|
mix pleroma.robots_txt disallow_all
|
||||||
|
```
|
|
@ -1 +0,0 @@
|
||||||
See `Authentication` section of [the configuration cheatsheet](../configuration/cheatsheet.md#authentication).
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,62 +0,0 @@
|
||||||
# How to use a different domain name for Pleroma and the users it serves
|
|
||||||
|
|
||||||
Pleroma users are primarily identified by a `user@example.org` handle, and you might want this identifier to be the same as your email or jabber account, for instance.
|
|
||||||
However, in this case, you are almost certainly serving some web content on `https://example.org` already, and you might want to use another domain (say `pleroma.example.org`) for Pleroma itself.
|
|
||||||
|
|
||||||
Pleroma supports that, but it might be tricky to set up, and any error might prevent you from federating with other instances.
|
|
||||||
|
|
||||||
*If you are already running Pleroma on `example.org`, it is no longer possible to move it to `pleroma.example.org`.*
|
|
||||||
|
|
||||||
## Account identifiers
|
|
||||||
|
|
||||||
It is important to understand that for federation purposes, a user in Pleroma has two unique identifiers associated:
|
|
||||||
|
|
||||||
- A webfinger `acct:` URI, used for discovery and as a verifiable global name for the user across Pleroma instances. In our example, our account's acct: URI is `acct:user@example.org`
|
|
||||||
- An author/actor URI, used in every other aspect of federation. This is the way in which users are identified in ActivityPub, the underlying protocol used for federation with other Pleroma instances.
|
|
||||||
In our case, it is `https://pleroma.example.org/users/user`.
|
|
||||||
|
|
||||||
Both account identifiers are unique and required for Pleroma. An important risk if you set up your Pleroma instance incorrectly is to create two users (with different acct: URIs) with conflicting author/actor URIs.
|
|
||||||
|
|
||||||
## WebFinger
|
|
||||||
|
|
||||||
As said earlier, each Pleroma user has an `acct`: URI, which is used for discovery and authentication. When you add @user@example.org, a webfinger query is performed. This is done in two steps:
|
|
||||||
|
|
||||||
1. Querying `https://example.org/.well-known/host-meta` (where the domain of the URL matches the domain part of the `acct`: URI) to get information on how to perform the query.
|
|
||||||
This file will indeed contain a URL template of the form `https://example.org/.well-known/webfinger?resource={uri}` that will be used in the second step.
|
|
||||||
2. Fill the returned template with the `acct`: URI to be queried and perform the query: `https://example.org/.well-known/webfinger?resource=acct:user@example.org`
|
|
||||||
|
|
||||||
## Configuring your Pleroma instance
|
|
||||||
|
|
||||||
**_DO NOT ATTEMPT TO CONFIGURE YOUR INSTANCE THIS WAY IF YOU DID NOT UNDERSTAND THE ABOVE_**
|
|
||||||
|
|
||||||
### Configuring Pleroma
|
|
||||||
|
|
||||||
Pleroma has a two configuration settings to enable using different domains for your users and Pleroma itself. `host` in `Pleroma.Web.Endpoint` and `domain` in `Pleroma.Web.WebFinger`. When the latter is not set, it defaults to the value of `host`.
|
|
||||||
|
|
||||||
*Be extra careful when configuring your Pleroma instance, as changing `host` may cause remote instances to register different accounts with the same author/actor URI, which will result in federation issues!*
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
|
||||||
url: [host: "pleroma.example.org"]
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.WebFinger, domain: "example.org"
|
|
||||||
```
|
|
||||||
|
|
||||||
- `domain` - is the domain for which your Pleroma instance has authority, it's the domain used in `acct:` URI. In our example, `domain` would be set to `example.org`. This is used in WebFinger account ids, which are the canonical account identifier in some other fediverse software like Mastodon. **If you change `domain`, the accounts on your server will be shown as different accounts in those software**.
|
|
||||||
- `host` - is the domain used for any URL generated for your instance, including the author/actor URL's. In our case, that would be `pleroma.example.org`. This is used in AP ids, which are the canonical account identifier in Pleroma and some other fediverse software. **You should not change this after you have set up the instance**.
|
|
||||||
|
|
||||||
### Configuring WebFinger domain
|
|
||||||
|
|
||||||
Now, you have Pleroma running at `https://pleroma.example.org` as well as a website at `https://example.org`. If you recall how webfinger queries work, the first step is to query `https://example.org/.well-known/host-meta`, which will contain an URL template.
|
|
||||||
|
|
||||||
Therefore, the easiest way to configure `example.org` is to redirect `/.well-known/host-meta` to `pleroma.example.org`.
|
|
||||||
|
|
||||||
With nginx, it would be as simple as adding:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
location = /.well-known/host-meta {
|
|
||||||
return 301 https://pleroma.example.org$request_uri;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
in example.org's server block.
|
|
|
@ -1,155 +0,0 @@
|
||||||
# How to activate Pleroma in-database configuration
|
|
||||||
## Explanation
|
|
||||||
|
|
||||||
The configuration of Pleroma has traditionally been managed with a config file, e.g. `config/prod.secret.exs`. This method requires a restart of the application for any configuration changes to take effect. We have made it possible to control most settings in the AdminFE interface after running a migration script.
|
|
||||||
|
|
||||||
## Migration to database config
|
|
||||||
|
|
||||||
1. Run the mix task to migrate to the database.
|
|
||||||
|
|
||||||
**Source:**
|
|
||||||
|
|
||||||
```
|
|
||||||
$ mix pleroma.config migrate_to_db
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
**OTP:**
|
|
||||||
|
|
||||||
*Note: OTP users need Pleroma to be running for `pleroma_ctl` commands to work*
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./bin/pleroma_ctl config migrate_to_db
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Migrating settings from file: /home/pleroma/config/dev.secret.exs
|
|
||||||
|
|
||||||
Settings for key instance migrated.
|
|
||||||
Settings for group :pleroma migrated.
|
|
||||||
```
|
|
||||||
|
|
||||||
2. It is recommended to backup your config file now.
|
|
||||||
|
|
||||||
```
|
|
||||||
cp config/dev.secret.exs config/dev.secret.exs.orig
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Edit your Pleroma config to enable database configuration:
|
|
||||||
|
|
||||||
```
|
|
||||||
config :pleroma, configurable_from_database: true
|
|
||||||
```
|
|
||||||
|
|
||||||
4. ⚠️ **THIS IS NOT REQUIRED** ⚠️
|
|
||||||
|
|
||||||
Now you can edit your config file and strip it down to the only settings which are not possible to control in the database. e.g., the Postgres (Repo) and webserver (Endpoint) settings cannot be controlled in the database because the application needs the settings to start up and access the database.
|
|
||||||
|
|
||||||
Any settings in the database will override those in the config file, but you may find it less confusing if the setting is only declared in one place.
|
|
||||||
|
|
||||||
A non-exhaustive list of settings that are only possible in the config file include the following:
|
|
||||||
|
|
||||||
* config :pleroma, Pleroma.Web.Endpoint
|
|
||||||
* config :pleroma, Pleroma.Repo
|
|
||||||
* config :pleroma, configurable\_from\_database
|
|
||||||
* config :pleroma, :database, rum_enabled
|
|
||||||
* config :pleroma, :connections_pool
|
|
||||||
|
|
||||||
Here is an example of a server config stripped down after migration:
|
|
||||||
|
|
||||||
```
|
|
||||||
import Config
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
|
||||||
url: [host: "cool.pleroma.site", scheme: "https", port: 443]
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
|
||||||
adapter: Ecto.Adapters.Postgres,
|
|
||||||
username: "pleroma",
|
|
||||||
password: "MySecretPassword",
|
|
||||||
database: "pleroma_prod",
|
|
||||||
hostname: "localhost"
|
|
||||||
|
|
||||||
config :pleroma, configurable_from_database: true
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Restart your instance and you can now access the Settings tab in AdminFE.
|
|
||||||
|
|
||||||
|
|
||||||
## Reverting back from database config
|
|
||||||
|
|
||||||
1. Run the mix task to migrate back from the database. You'll receive some debugging output and a few messages informing you of what happened.
|
|
||||||
|
|
||||||
**Source:**
|
|
||||||
|
|
||||||
```
|
|
||||||
$ mix pleroma.config migrate_from_db
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
**OTP:**
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./bin/pleroma_ctl config migrate_from_db
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
10:26:30.593 [debug] QUERY OK source="config" db=9.8ms decode=1.2ms queue=26.0ms idle=0.0ms
|
|
||||||
SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
|
|
||||||
|
|
||||||
10:26:30.659 [debug] QUERY OK source="config" db=1.1ms idle=80.7ms
|
|
||||||
SELECT c0."id", c0."key", c0."group", c0."value", c0."inserted_at", c0."updated_at" FROM "config" AS c0 []
|
|
||||||
Database configuration settings have been saved to config/dev.exported_from_db.secret.exs
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Remove `config :pleroma, configurable_from_database: true` from your config. The in-database configuration still exists, but it will not be used. Future migrations will erase the database config before importing your config file again.
|
|
||||||
|
|
||||||
3. Restart your instance.
|
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
### Clearing database config
|
|
||||||
You can clear the database config with the following command:
|
|
||||||
|
|
||||||
**Source:**
|
|
||||||
|
|
||||||
```
|
|
||||||
$ mix pleroma.config reset
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
**OTP:**
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./bin/pleroma_ctl config reset
|
|
||||||
```
|
|
||||||
|
|
||||||
Additionally, every time you migrate the configuration to the database the config table is automatically truncated to ensure a clean migration.
|
|
||||||
|
|
||||||
### Manually removing a setting
|
|
||||||
If you encounter a situation where the server cannot run properly because of an invalid setting in the database and this is preventing you from accessing AdminFE, you can manually remove the offending setting if you know which one it is.
|
|
||||||
|
|
||||||
e.g., here is an example showing a the removal of the `config :pleroma, :instance` settings:
|
|
||||||
|
|
||||||
**Source:**
|
|
||||||
|
|
||||||
```
|
|
||||||
$ mix pleroma.config delete pleroma instance
|
|
||||||
Are you sure you want to continue? [n] y
|
|
||||||
config :pleroma, :instance deleted from the ConfigDB.
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
**OTP:**
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./bin/pleroma_ctl config delete pleroma instance
|
|
||||||
Are you sure you want to continue? [n] y
|
|
||||||
config :pleroma, :instance deleted from the ConfigDB.
|
|
||||||
```
|
|
||||||
|
|
||||||
Now the `config :pleroma, :instance` settings have been removed from the database.
|
|
|
@ -1,136 +0,0 @@
|
||||||
# Configuring Ejabberd (XMPP Server) to use Pleroma for authentication
|
|
||||||
|
|
||||||
If you want to give your Pleroma users an XMPP (chat) account, you can configure [Ejabberd](https://github.com/processone/ejabberd) to use your Pleroma server for user authentication, automatically giving every local user an XMPP account.
|
|
||||||
|
|
||||||
In general, you just have to follow the configuration described at [https://docs.ejabberd.im/admin/configuration/authentication/#external-script](https://docs.ejabberd.im/admin/configuration/authentication/#external-script). Please read this section carefully.
|
|
||||||
|
|
||||||
Copy the script below to suitable path on your system and set owner and permissions. Also do not forget adjusting `PLEROMA_HOST` and `PLEROMA_PORT`, if necessary.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cp pleroma_ejabberd_auth.py /etc/ejabberd/pleroma_ejabberd_auth.py
|
|
||||||
chown ejabberd /etc/ejabberd/pleroma_ejabberd_auth.py
|
|
||||||
chmod 700 /etc/ejabberd/pleroma_ejabberd_auth.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Set external auth params in ejabberd.yaml file:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
auth_method: [external]
|
|
||||||
extauth_program: "python3 /etc/ejabberd/pleroma_ejabberd_auth.py"
|
|
||||||
extauth_instances: 3
|
|
||||||
auth_use_cache: false
|
|
||||||
```
|
|
||||||
|
|
||||||
Restart / reload your ejabberd service.
|
|
||||||
|
|
||||||
After restarting your Ejabberd server, your users should now be able to connect with their Pleroma credentials.
|
|
||||||
|
|
||||||
|
|
||||||
```python
|
|
||||||
import sys
|
|
||||||
import struct
|
|
||||||
import http.client
|
|
||||||
from base64 import b64encode
|
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
PLEROMA_HOST = "127.0.0.1"
|
|
||||||
PLEROMA_PORT = "4000"
|
|
||||||
AUTH_ENDPOINT = "/api/v1/accounts/verify_credentials"
|
|
||||||
USER_ENDPOINT = "/api/v1/accounts"
|
|
||||||
LOGFILE = "/var/log/ejabberd/pleroma_auth.log"
|
|
||||||
|
|
||||||
logging.basicConfig(filename=LOGFILE, level=logging.INFO)
|
|
||||||
|
|
||||||
|
|
||||||
# Pleroma functions
|
|
||||||
def create_connection():
|
|
||||||
return http.client.HTTPConnection(PLEROMA_HOST, PLEROMA_PORT)
|
|
||||||
|
|
||||||
|
|
||||||
def verify_credentials(user: str, password: str) -> bool:
|
|
||||||
user_pass_b64 = b64encode("{}:{}".format(
|
|
||||||
user, password).encode('utf-8')).decode("ascii")
|
|
||||||
params = {}
|
|
||||||
headers = {
|
|
||||||
"Authorization": "Basic {}".format(user_pass_b64)
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
conn = create_connection()
|
|
||||||
conn.request("GET", AUTH_ENDPOINT, params, headers)
|
|
||||||
|
|
||||||
response = conn.getresponse()
|
|
||||||
if response.status == 200:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
logging.info("Can not connect: %s", str(e))
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def does_user_exist(user: str) -> bool:
|
|
||||||
conn = create_connection()
|
|
||||||
conn.request("GET", "{}/{}".format(USER_ENDPOINT, user))
|
|
||||||
|
|
||||||
response = conn.getresponse()
|
|
||||||
if response.status == 200:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def auth(username: str, server: str, password: str) -> bool:
|
|
||||||
return verify_credentials(username, password)
|
|
||||||
|
|
||||||
|
|
||||||
def isuser(username, server):
|
|
||||||
return does_user_exist(username)
|
|
||||||
|
|
||||||
|
|
||||||
def read():
|
|
||||||
(pkt_size,) = struct.unpack('>H', bytes(sys.stdin.read(2), encoding='utf8'))
|
|
||||||
pkt = sys.stdin.read(pkt_size)
|
|
||||||
cmd = pkt.split(':')[0]
|
|
||||||
if cmd == 'auth':
|
|
||||||
username, server, password = pkt.split(':', 3)[1:]
|
|
||||||
write(auth(username, server, password))
|
|
||||||
elif cmd == 'isuser':
|
|
||||||
username, server = pkt.split(':', 2)[1:]
|
|
||||||
write(isuser(username, server))
|
|
||||||
elif cmd == 'setpass':
|
|
||||||
# u, s, p = pkt.split(':', 3)[1:]
|
|
||||||
write(False)
|
|
||||||
elif cmd == 'tryregister':
|
|
||||||
# u, s, p = pkt.split(':', 3)[1:]
|
|
||||||
write(False)
|
|
||||||
elif cmd == 'removeuser':
|
|
||||||
# u, s = pkt.split(':', 2)[1:]
|
|
||||||
write(False)
|
|
||||||
elif cmd == 'removeuser3':
|
|
||||||
# u, s, p = pkt.split(':', 3)[1:]
|
|
||||||
write(False)
|
|
||||||
else:
|
|
||||||
write(False)
|
|
||||||
|
|
||||||
|
|
||||||
def write(result):
|
|
||||||
if result:
|
|
||||||
sys.stdout.write('\x00\x02\x00\x01')
|
|
||||||
else:
|
|
||||||
sys.stdout.write('\x00\x02\x00\x00')
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
logging.info("Starting pleroma ejabberd auth daemon...")
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
read()
|
|
||||||
except Exception as e:
|
|
||||||
logging.info(
|
|
||||||
"Error while processing data from ejabberd %s", str(e))
|
|
||||||
pass
|
|
||||||
|
|
||||||
```
|
|
|
@ -1,34 +0,0 @@
|
||||||
# How to activate mediaproxy
|
|
||||||
## Explanation
|
|
||||||
|
|
||||||
Without the `mediaproxy` function, Pleroma doesn't store any remote content like pictures, video etc. locally. So every time you open Pleroma, the content is loaded from the source server, from where the post is coming. This can result in slowly loading content or/and increased bandwidth usage on the source server.
|
|
||||||
With the `mediaproxy` function you can use nginx to cache this content, so users can access it faster, because it's loaded from your server.
|
|
||||||
|
|
||||||
## Activate it
|
|
||||||
|
|
||||||
* Edit your nginx config and add the following location:
|
|
||||||
```
|
|
||||||
location /proxy {
|
|
||||||
proxy_cache pleroma_media_cache;
|
|
||||||
proxy_cache_lock on;
|
|
||||||
proxy_pass http://localhost:4000;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Also add the following on top of the configuration, outside of the `server` block:
|
|
||||||
```
|
|
||||||
proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off;
|
|
||||||
```
|
|
||||||
If you came here from one of the installation guides, take a look at the example configuration `/installation/pleroma.nginx`, where this part is already included.
|
|
||||||
|
|
||||||
* Append the following to your `prod.secret.exs` or `dev.secret.exs` (depends on which mode your instance is running):
|
|
||||||
```
|
|
||||||
config :pleroma, :media_proxy,
|
|
||||||
enabled: true,
|
|
||||||
proxy_opts: [
|
|
||||||
redirect_on_failure: true
|
|
||||||
]
|
|
||||||
#base_url: "https://cache.pleroma.social"
|
|
||||||
```
|
|
||||||
If you want to use a subdomain to serve the files, uncomment `base_url`, change the url and add a comma after `true` in the previous line.
|
|
||||||
|
|
||||||
* Restart nginx and Pleroma
|
|
|
@ -1,42 +0,0 @@
|
||||||
# How to enable text search for Chinese, Japanese and Korean
|
|
||||||
|
|
||||||
Pleroma's full text search feature is powered by PostgreSQL's native [text search](https://www.postgresql.org/docs/current/textsearch.html), it works well out of box for most of languages, but needs extra configurations for some asian languages like Chinese, Japanese and Korean (CJK).
|
|
||||||
|
|
||||||
|
|
||||||
## Setup and test the new search config
|
|
||||||
|
|
||||||
In most cases, you would need an extension installed to support parsing CJK text. Here are a few extensions you may choose from, or you are more than welcome to share additional ones you found working for you with the rest of Pleroma community.
|
|
||||||
|
|
||||||
* [a generic n-gram parser](https://github.com/huangjimmy/pg_cjk_parser) supports Simplifed/Traditional Chinese, Japanese, and Korean
|
|
||||||
* [a Korean parser](https://github.com/i0seph/textsearch_ko) based on mecab
|
|
||||||
* [a Japanese parser](https://www.amris.co.jp/tsja/index.html) based on mecab
|
|
||||||
* [zhparser](https://github.com/amutu/zhparser/) is a PostgreSQL extension base on the Simple Chinese Word Segmentation(SCWS)
|
|
||||||
* [another Chinese parser](https://github.com/jaiminpan/pg_jieba) based on Jieba Chinese Word Segmentation
|
|
||||||
|
|
||||||
Once you have the new search config , make sure you test it with the `pleroma` user in PostgreSQL (change `YOUR.CONFIG` to your real configuration name)
|
|
||||||
```
|
|
||||||
SELECT ts_debug('YOUR.CONFIG', '安装和配置Nginx, ElixirとErlangをインストールします');
|
|
||||||
```
|
|
||||||
Check output of the query, and see if it matches your expectation.
|
|
||||||
|
|
||||||
|
|
||||||
## Update text search config and index in database
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./bin/pleroma_ctl database set_text_search_config YOUR.CONFIG
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mix pleroma.database set_text_search_config YOUR.CONFIG
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: index update may take a while, and it can be done while the instance is up and running, so you may restart db connection as soon as you see `Recreate index` in task output.
|
|
||||||
|
|
||||||
## Restart database connection
|
|
||||||
Since some changes above will only apply with a new database connection, you will have to restart either Pleroma or PostgreSQL process, or use `pg_terminate_backend` SQL command without restarting either.
|
|
||||||
|
|
||||||
Now the search results of statuses should be much more friendly for your language of choice, the results for searching users and tags were not changed, as the default parsing/matching should work for most cases.
|
|
|
@ -1,33 +0,0 @@
|
||||||
# How to set rich media cache ttl based on image ttl
|
|
||||||
## Explanation
|
|
||||||
|
|
||||||
Richmedia are cached without the ttl but the rich media may have image which can expire, like aws signed url.
|
|
||||||
In such cases the old image url (expired) is returned from the media cache.
|
|
||||||
|
|
||||||
So to avoid such situation we can define a module that will set ttl based on image.
|
|
||||||
The module must adopt behaviour `Pleroma.Web.RichMedia.Parser.TTL`
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```exs
|
|
||||||
defmodule MyModule do
|
|
||||||
@behaviour Pleroma.Web.RichMedia.Parser.TTL
|
|
||||||
|
|
||||||
@impl Pleroma.Web.RichMedia.Parser.TTL
|
|
||||||
def ttl(data, url) do
|
|
||||||
image_url = Map.get(data, :image)
|
|
||||||
# do some parsing in the url and get the ttl of the image
|
|
||||||
# return ttl is unix time
|
|
||||||
parse_ttl_from_url(image_url)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
And update the config
|
|
||||||
|
|
||||||
```exs
|
|
||||||
config :pleroma, :rich_media,
|
|
||||||
ttl_setters: [Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl, MyModule]
|
|
||||||
```
|
|
||||||
|
|
||||||
> For reference there is a parser for AWS signed URL `Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl`, it's enabled by default.
|
|
|
@ -1,74 +0,0 @@
|
||||||
# Theming your instance
|
|
||||||
|
|
||||||
To add a custom theme to your instance, you'll first need to get a custom theme, upload it to the server, make it available to the instance and eventually you can set it as default.
|
|
||||||
|
|
||||||
## Getting a custom theme
|
|
||||||
|
|
||||||
### Create your own theme
|
|
||||||
|
|
||||||
* You can create your own theme using the Pleroma FE by going to settings (gear on the top right) and choose the Theme tab. Here you have the options to create a personal theme.
|
|
||||||
* To download your theme, you can do Save preset
|
|
||||||
* If you want to upload a theme to customise it further, you can upload it using Load preset
|
|
||||||
|
|
||||||
This will only save the theme for you personally. To make it available to the whole instance, you'll need to upload it to the server.
|
|
||||||
|
|
||||||
### Get an existing theme
|
|
||||||
|
|
||||||
* You can download a theme from another instance by going to that instance, go to settings and make sure you have the theme selected that you want. Then you can do Save preset to download it.
|
|
||||||
* You can also find and download custom themes at <https://plthemes.vulpes.one/>
|
|
||||||
|
|
||||||
## Adding the custom theme to the instance
|
|
||||||
|
|
||||||
### Upload the theme to the server
|
|
||||||
|
|
||||||
Themes can be found in the [static directory](static_dir.md). Create `STATIC-DIR/static/themes/` if needed and copy your theme there. Next you need to add an entry for your theme to `STATIC-DIR/static/styles.json`. If you use a from source installation, you'll first need to copy the file from `priv/static/static/styles.json`.
|
|
||||||
|
|
||||||
Example of `styles.json` where we add our own `my-awesome-theme.json`
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
|
|
||||||
"pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
|
|
||||||
"classic-dark": [ "Classic Dark", "#161c20", "#282e32", "#b9b9b9", "#baaa9c", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
|
|
||||||
"bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"],
|
|
||||||
"ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ],
|
|
||||||
"monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ],
|
|
||||||
|
|
||||||
"redmond-xx": "/static/themes/redmond-xx.json",
|
|
||||||
"redmond-xx-se": "/static/themes/redmond-xx-se.json",
|
|
||||||
"redmond-xxi": "/static/themes/redmond-xxi.json",
|
|
||||||
"breezy-dark": "/static/themes/breezy-dark.json",
|
|
||||||
"breezy-light": "/static/themes/breezy-light.json",
|
|
||||||
"mammal": "/static/themes/mammal.json",
|
|
||||||
"my-awesome-theme": "/static/themes/my-awesome-theme.json"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you'll already be able to select the theme in Pleroma FE from the drop-down. You don't need to restart Pleroma because we only changed static served files. You may need to refresh the page in your browser. You'll notice however that the theme doesn't have a name, it's just an empty entry in the drop-down.
|
|
||||||
|
|
||||||
### Give the theme a name
|
|
||||||
|
|
||||||
When you open one of the themes that ship with Pleroma, you'll notice that the json has a `"name"` key. Add a key-value pair to your theme where the key name is `"name"` and the value the name you want to give your theme. After this you can refresh te page in your browser and the name should be visible in the drop-down.
|
|
||||||
|
|
||||||
Example of `my-awesome-theme.json` where we add the name "My Awesome Theme"
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"_pleroma_theme_version": 2,
|
|
||||||
"name": "My Awesome Theme",
|
|
||||||
"theme": {}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set as default theme
|
|
||||||
|
|
||||||
Now we can set the new theme as default in the [Pleroma FE configuration](../../../frontend/CONFIGURATION).
|
|
||||||
|
|
||||||
Example of adding the new theme in the back-end config files
|
|
||||||
```elixir
|
|
||||||
config :pleroma, :frontend_configurations,
|
|
||||||
pleroma_fe: %{
|
|
||||||
theme: "my-awesome-theme"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If you added it in the back-end configuration file, you'll need to restart your instance for the changes to take effect. If you don't see the changes, it's probably because the browser has cached the previous theme. In that case you'll want to clear browser caches. Alternatively you can use a private/incognito window just to see the changes.
|
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
# Message Rewrite Facility
|
|
||||||
|
|
||||||
The Message Rewrite Facility (MRF) is a subsystem that is implemented as a series of hooks that allows the administrator to rewrite or discard messages.
|
|
||||||
|
|
||||||
Possible uses include:
|
|
||||||
|
|
||||||
* marking incoming messages with media from a given account or instance as sensitive
|
|
||||||
* rejecting messages from a specific instance
|
|
||||||
* rejecting reports (flags) from a specific instance
|
|
||||||
* removing/unlisting messages from the public timelines
|
|
||||||
* removing media from messages
|
|
||||||
* sending only public messages to a specific instance
|
|
||||||
|
|
||||||
The MRF provides user-configurable policies. The default policy is `NoOpPolicy`, which disables the MRF functionality. Pleroma also includes an easy to use policy called `SimplePolicy` which maps messages matching certain pre-defined criterion to actions built into the policy module.
|
|
||||||
|
|
||||||
It is possible to use multiple, active MRF policies at the same time.
|
|
||||||
|
|
||||||
## Quarantine Instances
|
|
||||||
|
|
||||||
You have the ability to prevent from private / followers-only messages from federating with specific instances. Which means they will only get the public or unlisted messages from your instance.
|
|
||||||
|
|
||||||
If, for example, you're using `MIX_ENV=prod` aka using production mode, you would open your configuration file located in `config/prod.secret.exs` and edit or add the option under your `:instance` config object. Then you would specify the instance within quotes.
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, :instance,
|
|
||||||
[...]
|
|
||||||
quarantined_instances: ["instance.example", "other.example"]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using `SimplePolicy`
|
|
||||||
|
|
||||||
`SimplePolicy` is capable of handling most common admin tasks.
|
|
||||||
|
|
||||||
To use `SimplePolicy`, you must enable it. Do so by adding the following to your `:instance` config object, so that it looks like this:
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, :mrf,
|
|
||||||
[...]
|
|
||||||
policies: Pleroma.Web.ActivityPub.MRF.SimplePolicy
|
|
||||||
```
|
|
||||||
|
|
||||||
Once `SimplePolicy` is enabled, you can configure various groups in the `:mrf_simple` config object. These groups are:
|
|
||||||
|
|
||||||
* `reject`: Servers in this group will have their messages rejected.
|
|
||||||
* `accept`: If not empty, only messages from these instances will be accepted (whitelist federation).
|
|
||||||
* `media_nsfw`: Servers in this group will have the #nsfw tag and sensitive setting injected into incoming messages which contain media.
|
|
||||||
* `media_removal`: Servers in this group will have media stripped from incoming messages.
|
|
||||||
* `avatar_removal`: Avatars from these servers will be stripped from incoming messages.
|
|
||||||
* `banner_removal`: Banner images from these servers will be stripped from incoming messages.
|
|
||||||
* `report_removal`: Servers in this group will have their reports (flags) rejected.
|
|
||||||
* `federated_timeline_removal`: Servers in this group will have their messages unlisted from the public timelines by flipping the `to` and `cc` fields.
|
|
||||||
* `reject_deletes`: Deletion requests will be rejected from these servers.
|
|
||||||
|
|
||||||
Servers should be configured as lists.
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
This example will enable `SimplePolicy`, block media from `illegalporn.biz`, mark media as NSFW from `porn.biz` and `porn.business`, reject messages from `spam.com`, remove messages from `spam.university` from the federated timeline and block reports (flags) from `whiny.whiner`. We also give a reason why the moderation was done:
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, :mrf,
|
|
||||||
policies: [Pleroma.Web.ActivityPub.MRF.SimplePolicy]
|
|
||||||
|
|
||||||
config :pleroma, :mrf_simple,
|
|
||||||
media_removal: [{"illegalporn.biz", "Media can contain illegal contant"}],
|
|
||||||
media_nsfw: [{"porn.biz", "unmarked nsfw media"}, {"porn.business", "A lot of unmarked nsfw media"}],
|
|
||||||
reject: [{"spam.com", "They keep spamming our users"}],
|
|
||||||
federated_timeline_removal: [{"spam.university", "Annoying low-quality posts who otherwise fill up TWKN"}],
|
|
||||||
report_removal: [{"whiny.whiner", "Keep spamming us with irrelevant reports"}]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Use with Care
|
|
||||||
|
|
||||||
The effects of MRF policies can be very drastic. It is important to use this functionality carefully. Always try to talk to an admin before writing an MRF policy concerning their instance.
|
|
||||||
|
|
||||||
## Writing your own MRF Policy
|
|
||||||
|
|
||||||
As discussed above, the MRF system is a modular system that supports pluggable policies. This means that an admin may write a custom MRF policy in Elixir or any other language that runs on the Erlang VM, by specifying the module name in the `policies` config setting.
|
|
||||||
|
|
||||||
For example, here is a sample policy module which rewrites all messages to "new message content":
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
defmodule Pleroma.Web.ActivityPub.MRF.RewritePolicy do
|
|
||||||
@moduledoc "MRF policy which rewrites all Notes to have 'new message content'."
|
|
||||||
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
|
||||||
|
|
||||||
# Catch messages which contain Note objects with actual data to filter.
|
|
||||||
# Capture the object as `object`, the message content as `content` and the
|
|
||||||
# message itself as `message`.
|
|
||||||
@impl true
|
|
||||||
def filter(
|
|
||||||
%{"type" => "Create", "object" => %{"type" => "Note", "content" => content} = object} =
|
|
||||||
message
|
|
||||||
)
|
|
||||||
when is_binary(content) do
|
|
||||||
# Subject / CW is stored as summary instead of `name` like other AS2 objects
|
|
||||||
# because of Mastodon doing it that way.
|
|
||||||
summary = object["summary"]
|
|
||||||
|
|
||||||
# Message edits go here.
|
|
||||||
content = "new message content"
|
|
||||||
|
|
||||||
# Assemble the mutated object.
|
|
||||||
object =
|
|
||||||
object
|
|
||||||
|> Map.put("content", content)
|
|
||||||
|> Map.put("summary", summary)
|
|
||||||
|
|
||||||
# Assemble the mutated message.
|
|
||||||
message = Map.put(message, "object", object)
|
|
||||||
{:ok, message}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Let all other messages through without modifying them.
|
|
||||||
@impl true
|
|
||||||
def filter(message), do: {:ok, message}
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def describe do
|
|
||||||
{:ok, %{mrf_sample: %{content: "new message content"}}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
If you save this file as `lib/pleroma/web/activity_pub/mrf/rewrite_policy.ex`, it will be included when you next rebuild Pleroma. You can enable it in the configuration like so:
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, :mrf,
|
|
||||||
policies: [
|
|
||||||
Pleroma.Web.ActivityPub.MRF.SimplePolicy,
|
|
||||||
Pleroma.Web.ActivityPub.MRF.RewritePolicy
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
Please note that the Pleroma developers consider custom MRF policy modules to fall under the purview of the AGPL. As such, you are obligated to release the sources to your custom MRF policy modules upon request.
|
|
||||||
|
|
||||||
### MRF policies descriptions
|
|
||||||
|
|
||||||
If MRF policy depends on config, it can be added into MRF tab to adminFE by adding `config_description/0` method, which returns a map with a specific structure. See existing MRF's like `lib/pleroma/web/activity_pub/mrf/activity_expiration_policy.ex` for examples. Note that more complex inputs, like tuples or maps, may need extra changes in the adminFE and just adding it to `config_description/0` may not be enough to get these inputs working from the adminFE.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
%{
|
|
||||||
key: :mrf_activity_expiration,
|
|
||||||
related_policy: "Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy",
|
|
||||||
label: "MRF Activity Expiration Policy",
|
|
||||||
description: "Adds automatic expiration to all local activities",
|
|
||||||
children: [
|
|
||||||
%{
|
|
||||||
key: :days,
|
|
||||||
type: :integer,
|
|
||||||
description: "Default global expiration time for all local activities (in days)",
|
|
||||||
suggestions: [90, 365]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,66 +0,0 @@
|
||||||
# Optimizing the BEAM
|
|
||||||
|
|
||||||
Pleroma is built upon the Erlang/OTP VM known as BEAM. The BEAM VM is highly optimized for latency, but this has drawbacks in environments without dedicated hardware. One of the tricks used by the BEAM VM is [busy waiting](https://en.wikipedia.org/wiki/Busy_waiting). This allows the application to pretend to be busy working so the OS kernel does not pause the application process and switch to another process waiting for the CPU to execute its workload. It does this by spinning for a period of time which inflates the apparent CPU usage of the application so it is immediately ready to execute another task. This can be observed with utilities like **top(1)** which will show consistently high CPU usage for the process. Switching between procesess is a rather expensive operation and also clears CPU caches further affecting latency and performance. The goal of busy waiting is to avoid this penalty.
|
|
||||||
|
|
||||||
This strategy is very successful in making a performant and responsive application, but is not desirable on Virtual Machines or hardware with few CPU cores. Pleroma instances are often deployed on the same server as the required PostgreSQL database which can lead to situations where the Pleroma application is holding the CPU in a busy-wait loop and as a result the database cannot process requests in a timely manner. The fewer CPUs available, the more this problem is exacerbated. The latency is further amplified by the OS being installed on a Virtual Machine as the Hypervisor uses CPU time-slicing to pause the entire OS and switch between other tasks.
|
|
||||||
|
|
||||||
More adventurous admins can be creative with CPU affinity (e.g., *taskset* for Linux and *cpuset* on FreeBSD) to pin processes to specific CPUs and eliminate much of this contention. The most important advice is to run as few processes as possible on your server to achieve the best performance. Even idle background processes can occasionally create [software interrupts](https://en.wikipedia.org/wiki/Interrupt) and take attention away from the executing process creating latency spikes and invalidation of the CPU caches as they must be cleared when switching between processes for security.
|
|
||||||
|
|
||||||
Please only change these settings if you are experiencing issues or really know what you are doing. In general, there's no need to change these settings.
|
|
||||||
|
|
||||||
## VPS Provider Recommendations
|
|
||||||
|
|
||||||
### Good
|
|
||||||
|
|
||||||
* Hetzner Cloud
|
|
||||||
|
|
||||||
### Bad
|
|
||||||
|
|
||||||
* AWS (known to use burst scheduling)
|
|
||||||
|
|
||||||
|
|
||||||
## Example configurations
|
|
||||||
|
|
||||||
Tuning the BEAM requires you provide a config file normally called [vm.args](http://erlang.org/doc/man/erl.html#emulator-flags). If you are using systemd to manage the service you can modify the unit file as such:
|
|
||||||
|
|
||||||
`ExecStart=/usr/bin/elixir --erl '-args_file /opt/pleroma/config/vm.args' -S /usr/bin/mix phx.server`
|
|
||||||
|
|
||||||
Check your OS documentation to adopt a similar strategy on other platforms.
|
|
||||||
|
|
||||||
### Virtual Machine and/or few CPU cores
|
|
||||||
|
|
||||||
Disable the busy-waiting. This should generally only be done if you're on a platform that does burst scheduling, like AWS.
|
|
||||||
|
|
||||||
**vm.args:**
|
|
||||||
|
|
||||||
```
|
|
||||||
+sbwt none
|
|
||||||
+sbwtdcpu none
|
|
||||||
+sbwtdio none
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dedicated Hardware
|
|
||||||
|
|
||||||
Enable more busy waiting, increase the internal maximum limit of BEAM processes and ports. You can use this if you run on dedicated hardware, but it is not necessary.
|
|
||||||
|
|
||||||
**vm.args:**
|
|
||||||
|
|
||||||
```
|
|
||||||
+P 16777216
|
|
||||||
+Q 16777216
|
|
||||||
+K true
|
|
||||||
+A 128
|
|
||||||
+sbt db
|
|
||||||
+sbwt very_long
|
|
||||||
+swt very_low
|
|
||||||
+sub true
|
|
||||||
+Mulmbcs 32767
|
|
||||||
+Mumbcgs 1
|
|
||||||
+Musmbcs 2047
|
|
||||||
```
|
|
||||||
|
|
||||||
## Additional Reading
|
|
||||||
|
|
||||||
* [WhatsApp: Scaling to Millions of Simultaneous Connections](https://www.erlang-factory.com/upload/presentations/558/efsf2012-whatsapp-scaling.pdf)
|
|
||||||
* [Preemptive Scheduling and Spinlocks](https://www.uio.no/studier/emner/matnat/ifi/nedlagte-emner/INF3150/h03/annet/slides/preemptive.pdf)
|
|
||||||
* [The Curious Case of BEAM CPU Usage](https://stressgrid.com/blog/beam_cpu_usage/)
|
|
|
@ -1,48 +0,0 @@
|
||||||
# Optimizing PostgreSQL performance
|
|
||||||
|
|
||||||
Pleroma performance is largely dependent on performance of the underlying database. Better performance can be achieved by adjusting a few settings.
|
|
||||||
|
|
||||||
## PGTune
|
|
||||||
|
|
||||||
[PgTune](https://pgtune.leopard.in.ua) can be used to get recommended settings. Be sure to set "Number of Connections" to 20, otherwise it might produce settings hurtful to database performance. It is also recommended to not use "Network Storage" option.
|
|
||||||
|
|
||||||
## Disable generic query plans
|
|
||||||
|
|
||||||
When PostgreSQL receives a query, it decides on a strategy for searching the requested data, this is called a query plan. The query planner has two modes: generic and custom. Generic makes a plan for all queries of the same shape, ignoring the parameters, which is then cached and reused. Custom, on the contrary, generates a unique query plan based on query parameters.
|
|
||||||
|
|
||||||
By default PostgreSQL has an algorithm to decide which mode is more efficient for particular query, however this algorithm has been observed to be wrong on some of the queries Pleroma sends, leading to serious performance loss. Therefore, it is recommended to disable generic mode.
|
|
||||||
|
|
||||||
|
|
||||||
Pleroma already avoids generic query plans by default, however the method it uses is not the most efficient because it needs to be compatible with all supported PostgreSQL versions. For PostgreSQL 12 and higher additional performance can be gained by adding the following to Pleroma configuration:
|
|
||||||
```elixir
|
|
||||||
config :pleroma, Pleroma.Repo,
|
|
||||||
prepare: :named,
|
|
||||||
parameters: [
|
|
||||||
plan_cache_mode: "force_custom_plan"
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
A more detailed explaination of the issue can be found at <https://blog.soykaf.com/post/postgresql-elixir-troubles/>.
|
|
||||||
|
|
||||||
## Example configurations
|
|
||||||
|
|
||||||
Here are some configuration suggestions for PostgreSQL 10+.
|
|
||||||
|
|
||||||
### 1GB RAM, 1 CPU
|
|
||||||
```
|
|
||||||
shared_buffers = 256MB
|
|
||||||
effective_cache_size = 768MB
|
|
||||||
maintenance_work_mem = 64MB
|
|
||||||
work_mem = 13107kB
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2GB RAM, 2 CPU
|
|
||||||
```
|
|
||||||
shared_buffers = 512MB
|
|
||||||
effective_cache_size = 1536MB
|
|
||||||
maintenance_work_mem = 128MB
|
|
||||||
work_mem = 26214kB
|
|
||||||
max_worker_processes = 2
|
|
||||||
max_parallel_workers_per_gather = 1
|
|
||||||
max_parallel_workers = 2
|
|
||||||
```
|
|
|
@ -1,95 +0,0 @@
|
||||||
# Static Directory
|
|
||||||
|
|
||||||
Static frontend files are shipped with pleroma. If you want to overwrite or update these without problems during upgrades, you can write your custom versions to the static directory.
|
|
||||||
|
|
||||||
You can find the location of the static directory in the [configuration](../cheatsheet/#instance).
|
|
||||||
|
|
||||||
=== "OTP"
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, :instance,
|
|
||||||
static_dir: "/var/lib/pleroma/static/"
|
|
||||||
```
|
|
||||||
|
|
||||||
=== "From Source"
|
|
||||||
|
|
||||||
```elixir
|
|
||||||
config :pleroma, :instance,
|
|
||||||
static_dir: "instance/static/"
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, you can overwrite this value in your configuration to use a different static instance directory.
|
|
||||||
|
|
||||||
This document is written using `$static_dir` as the value of the `config :pleroma, :instance, static_dir` setting.
|
|
||||||
|
|
||||||
If you use a From Source installation and want to manage your custom files in the git repository, you can remove the `instance/` entry from `.gitignore`.
|
|
||||||
|
|
||||||
## robots.txt
|
|
||||||
|
|
||||||
There's a mix tasks to [generate a new robot.txt](../../administration/CLI_tasks/robots_txt/).
|
|
||||||
|
|
||||||
For more complex things, you can write your own robots.txt to `$static_dir/robots.txt`.
|
|
||||||
|
|
||||||
E.g. if you want to block all crawlers except for [fediverse.network](https://fediverse.network/about) you can use
|
|
||||||
|
|
||||||
```
|
|
||||||
User-Agent: *
|
|
||||||
Disallow: /
|
|
||||||
|
|
||||||
User-Agent: crawler-us-il-1.fediverse.network
|
|
||||||
Allow: /
|
|
||||||
|
|
||||||
User-Agent: makhnovtchina.random.sh
|
|
||||||
Allow: /
|
|
||||||
```
|
|
||||||
|
|
||||||
## Thumbnail
|
|
||||||
|
|
||||||
Add `$static_dir/instance/thumbnail.jpeg` with your selfie or other neat picture. It will be available on `http://your-domain.tld/instance/thumbnail.jpeg` and can be used by external applications.
|
|
||||||
|
|
||||||
## Instance-specific panel
|
|
||||||
|
|
||||||
Create and Edit your file at `$static_dir/instance/panel.html`.
|
|
||||||
|
|
||||||
## Background
|
|
||||||
|
|
||||||
You can change the background of your Pleroma instance by uploading it to `$static_dir/`, and then changing `background` in [your configuration](../cheatsheet/#frontend_configurations) accordingly.
|
|
||||||
|
|
||||||
E.g. if you put `$static_dir/images/background.jpg`
|
|
||||||
|
|
||||||
```
|
|
||||||
config :pleroma, :frontend_configurations,
|
|
||||||
pleroma_fe: %{
|
|
||||||
background: "/images/background.jpg"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Logo
|
|
||||||
|
|
||||||
!!! important
|
|
||||||
Note the extra `static` folder for the default logo.png location
|
|
||||||
|
|
||||||
If you want to give a brand to your instance, You can change the logo of your instance by uploading it to the static directory `$static_dir/static/logo.png`.
|
|
||||||
|
|
||||||
Alternatively, you can specify the path to your logo in [your configuration](../cheatsheet/#frontend_configurations).
|
|
||||||
|
|
||||||
E.g. if you put `$static_dir/static/mylogo-file.png`
|
|
||||||
|
|
||||||
```
|
|
||||||
config :pleroma, :frontend_configurations,
|
|
||||||
pleroma_fe: %{
|
|
||||||
logo: "/static/mylogo-file.png"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Terms of Service
|
|
||||||
|
|
||||||
!!! important
|
|
||||||
Note the extra `static` folder for the terms-of-service.html
|
|
||||||
|
|
||||||
Terms of Service will be shown to all users on the registration page. It's the best place where to write down the rules for your instance. You can modify the rules by adding and changing `$static_dir/static/terms-of-service.html`.
|
|
||||||
|
|
||||||
|
|
||||||
## Styling rendered pages
|
|
||||||
|
|
||||||
To overwrite the CSS stylesheet of the OAuth form and other static pages, you can upload your own CSS file to `instance/static/static.css`. This will completely replace the CSS used by those pages, so it might be a good idea to copy the one from `priv/static/instance/static.css` and make your changes.
|
|
|
@ -1,38 +0,0 @@
|
||||||
# Storing Remote Media
|
|
||||||
|
|
||||||
Pleroma does not store remote/federated media by default. The best way to achieve this is to change Nginx to keep its reverse proxy cache
|
|
||||||
for a year and to activate the `MediaProxyWarmingPolicy` MRF policy in Pleroma which will automatically fetch all media through the proxy
|
|
||||||
as soon as the post is received by your instance.
|
|
||||||
|
|
||||||
## Nginx
|
|
||||||
|
|
||||||
```
|
|
||||||
proxy_cache_path /long/term/storage/path/pleroma-media-cache levels=1:2
|
|
||||||
keys_zone=pleroma_media_cache:10m inactive=1y use_temp_path=off;
|
|
||||||
|
|
||||||
location ~ ^/(media|proxy) {
|
|
||||||
proxy_cache pleroma_media_cache;
|
|
||||||
slice 1m;
|
|
||||||
proxy_cache_key $host$uri$is_args$args$slice_range;
|
|
||||||
proxy_set_header Range $slice_range;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_cache_valid 206 301 302 304 1h;
|
|
||||||
proxy_cache_valid 200 1y;
|
|
||||||
proxy_cache_use_stale error timeout invalid_header updating;
|
|
||||||
proxy_ignore_client_abort on;
|
|
||||||
proxy_buffering on;
|
|
||||||
chunked_transfer_encoding on;
|
|
||||||
proxy_ignore_headers Cache-Control Expires;
|
|
||||||
proxy_hide_header Cache-Control Expires;
|
|
||||||
proxy_pass http://127.0.0.1:4000;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pleroma
|
|
||||||
|
|
||||||
Add to your `prod.secret.exs`:
|
|
||||||
|
|
||||||
```
|
|
||||||
config :pleroma, :mrf,
|
|
||||||
policies: [Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy]
|
|
||||||
```
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,255 +0,0 @@
|
||||||
# Chats
|
|
||||||
|
|
||||||
Chats are a way to represent an IM-style conversation between two actors. They are not the same as direct messages and they are not `Status`es, even though they have a lot in common.
|
|
||||||
|
|
||||||
## Why Chats?
|
|
||||||
|
|
||||||
There are no 'visibility levels' in ActivityPub, their definition is purely a Mastodon convention. Direct Messaging between users on the fediverse has mostly been modeled by using ActivityPub addressing following Mastodon conventions on normal `Note` objects. In this case, a 'direct message' would be a message that has no followers addressed and also does not address the special public actor, but just the recipients in the `to` field. It would still be a `Note` and is presented with other `Note`s as a `Status` in the API.
|
|
||||||
|
|
||||||
This is an awkward setup for a few reasons:
|
|
||||||
|
|
||||||
- As DMs generally still follow the usual `Status` conventions, it is easy to accidentally pull somebody into a DM thread by mentioning them. (e.g. "I hate @badguy so much")
|
|
||||||
- It is possible to go from a publicly addressed `Status` to a DM reply, back to public, then to a 'followers only' reply, and so on. This can be become very confusing, as it is unclear which user can see which part of the conversation.
|
|
||||||
- The standard `Status` format of implicit addressing also leads to rather ugly results if you try to display the messages as a chat, because all the recipients are always mentioned by name in the message.
|
|
||||||
- As direct messages are posted with the same api call (and usually same frontend component) as public messages, accidentally making a public message private or vice versa can happen easily. Client bugs can also lead to this, accidentally making private messages public.
|
|
||||||
|
|
||||||
As a measure to improve this situation, the `Conversation` concept and related Pleroma extensions were introduced. While it made it possible to work around a few of the issues, many of the problems remained and it didn't see much adoption because it was too complicated to use correctly.
|
|
||||||
|
|
||||||
## Chats explained
|
|
||||||
For this reasons, Chats are a new and different entity, both in the API as well as in ActivityPub. A quick overview:
|
|
||||||
|
|
||||||
- Chats are meant to represent an instant message conversation between two actors. For now these are only 1-on-1 conversations, but the other actor can be a group in the future.
|
|
||||||
- Chat messages have the ActivityPub type `ChatMessage`. They are not `Note`s. Servers that don't understand them will just drop them.
|
|
||||||
- The only addressing allowed in `ChatMessage`s is one single ActivityPub actor in the `to` field.
|
|
||||||
- There's always only one Chat between two actors. If you start chatting with someone and later start a 'new' Chat, the old Chat will be continued.
|
|
||||||
- `ChatMessage`s are posted with a different api, making it very hard to accidentally send a message to the wrong person.
|
|
||||||
- `ChatMessage`s don't show up in the existing timelines.
|
|
||||||
- Chats can never go from private to public. They are always private between the two actors.
|
|
||||||
|
|
||||||
## Caveats
|
|
||||||
|
|
||||||
- Chats are NOT E2E encrypted (yet). Security is still the same as email.
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
In general, the way to send a `ChatMessage` is to first create a `Chat`, then post a message to that `Chat`. `Group`s will later be supported by making them a sub-type of `Account`.
|
|
||||||
|
|
||||||
This is the overview of using the API. The API is also documented via OpenAPI, so you can view it and play with it by pointing SwaggerUI or a similar OpenAPI tool to `https://yourinstance.tld/api/openapi`.
|
|
||||||
|
|
||||||
### Creating or getting a chat.
|
|
||||||
|
|
||||||
To create or get an existing Chat for a certain recipient (identified by Account ID)
|
|
||||||
you can call:
|
|
||||||
|
|
||||||
`POST /api/v1/pleroma/chats/by-account-id/:account_id`
|
|
||||||
|
|
||||||
The account id is the normal FlakeId of the user
|
|
||||||
```
|
|
||||||
POST /api/v1/pleroma/chats/by-account-id/someflakeid
|
|
||||||
```
|
|
||||||
|
|
||||||
If you already have the id of a chat, you can also use
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/v1/pleroma/chats/:id
|
|
||||||
```
|
|
||||||
|
|
||||||
There will only ever be ONE Chat for you and a given recipient, so this call
|
|
||||||
will return the same Chat if you already have one with that user.
|
|
||||||
|
|
||||||
Returned data:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"account": {
|
|
||||||
"id": "someflakeid",
|
|
||||||
"username": "somenick",
|
|
||||||
...
|
|
||||||
},
|
|
||||||
"id" : "1",
|
|
||||||
"unread" : 2,
|
|
||||||
"last_message" : {...}, // The last message in that chat
|
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Marking a chat as read
|
|
||||||
|
|
||||||
To mark a number of messages in a chat up to a certain message as read, you can use
|
|
||||||
|
|
||||||
`POST /api/v1/pleroma/chats/:id/read`
|
|
||||||
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
- last_read_id: Given this id, all chat messages until this one will be marked as read. Required.
|
|
||||||
|
|
||||||
|
|
||||||
Returned data:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"account": {
|
|
||||||
"id": "someflakeid",
|
|
||||||
"username": "somenick",
|
|
||||||
...
|
|
||||||
},
|
|
||||||
"id" : "1",
|
|
||||||
"unread" : 0,
|
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Marking a single chat message as read
|
|
||||||
|
|
||||||
To set the `unread` property of a message to `false`
|
|
||||||
|
|
||||||
`POST /api/v1/pleroma/chats/:id/messages/:message_id/read`
|
|
||||||
|
|
||||||
Returned data:
|
|
||||||
|
|
||||||
The modified chat message
|
|
||||||
|
|
||||||
### Getting a list of Chats
|
|
||||||
|
|
||||||
`GET /api/v1/pleroma/chats`
|
|
||||||
|
|
||||||
This will return a list of chats that you have been involved in, sorted by their
|
|
||||||
last update (so new chats will be at the top).
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
|
|
||||||
- with_muted: Include chats from muted users (boolean).
|
|
||||||
|
|
||||||
Returned data:
|
|
||||||
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"account": {
|
|
||||||
"id": "someflakeid",
|
|
||||||
"username": "somenick",
|
|
||||||
...
|
|
||||||
},
|
|
||||||
"id" : "1",
|
|
||||||
"unread" : 2,
|
|
||||||
"last_message" : {...}, // The last message in that chat
|
|
||||||
"updated_at": "2020-04-21T15:11:46.000Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
The recipient of messages that are sent to this chat is given by their AP ID.
|
|
||||||
No pagination is implemented for now.
|
|
||||||
|
|
||||||
### Getting the messages for a Chat
|
|
||||||
|
|
||||||
For a given Chat id, you can get the associated messages with
|
|
||||||
|
|
||||||
`GET /api/v1/pleroma/chats/:id/messages`
|
|
||||||
|
|
||||||
This will return all messages, sorted by most recent to least recent. The usual
|
|
||||||
pagination options are implemented.
|
|
||||||
|
|
||||||
Returned data:
|
|
||||||
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"account_id": "someflakeid",
|
|
||||||
"chat_id": "1",
|
|
||||||
"content": "Check this out :firefox:",
|
|
||||||
"created_at": "2020-04-21T15:11:46.000Z",
|
|
||||||
"emojis": [
|
|
||||||
{
|
|
||||||
"shortcode": "firefox",
|
|
||||||
"static_url": "https://dontbulling.me/emoji/Firefox.gif",
|
|
||||||
"url": "https://dontbulling.me/emoji/Firefox.gif",
|
|
||||||
"visible_in_picker": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"id": "13",
|
|
||||||
"unread": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"account_id": "someflakeid",
|
|
||||||
"chat_id": "1",
|
|
||||||
"content": "Whats' up?",
|
|
||||||
"created_at": "2020-04-21T15:06:45.000Z",
|
|
||||||
"emojis": [],
|
|
||||||
"id": "12",
|
|
||||||
"unread": false,
|
|
||||||
"idempotency_key": "75442486-0874-440c-9db1-a7006c25a31f"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
- idempotency_key: The copy of the `idempotency-key` HTTP request header that can be used for optimistic message sending. Included only during the first few minutes after the message creation.
|
|
||||||
|
|
||||||
### Posting a chat message
|
|
||||||
|
|
||||||
Posting a chat message for given Chat id works like this:
|
|
||||||
|
|
||||||
`POST /api/v1/pleroma/chats/:id/messages`
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
- content: The text content of the message. Optional if media is attached.
|
|
||||||
- media_id: The id of an upload that will be attached to the message.
|
|
||||||
|
|
||||||
Currently, no formatting beyond basic escaping and emoji is implemented.
|
|
||||||
|
|
||||||
Returned data:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"account_id": "someflakeid",
|
|
||||||
"chat_id": "1",
|
|
||||||
"content": "Check this out :firefox:",
|
|
||||||
"created_at": "2020-04-21T15:11:46.000Z",
|
|
||||||
"emojis": [
|
|
||||||
{
|
|
||||||
"shortcode": "firefox",
|
|
||||||
"static_url": "https://dontbulling.me/emoji/Firefox.gif",
|
|
||||||
"url": "https://dontbulling.me/emoji/Firefox.gif",
|
|
||||||
"visible_in_picker": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"id": "13",
|
|
||||||
"unread": false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deleting a chat message
|
|
||||||
|
|
||||||
Deleting a chat message for given Chat id works like this:
|
|
||||||
|
|
||||||
`DELETE /api/v1/pleroma/chats/:chat_id/messages/:message_id`
|
|
||||||
|
|
||||||
Returned data is the deleted message.
|
|
||||||
|
|
||||||
### Notifications
|
|
||||||
|
|
||||||
There's a new `pleroma:chat_mention` notification, which has this form. It is not given out in the notifications endpoint by default, you need to explicitly request it with `include_types[]=pleroma:chat_mention`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "someid",
|
|
||||||
"type": "pleroma:chat_mention",
|
|
||||||
"account": { ... } // User account of the sender,
|
|
||||||
"chat_message": {
|
|
||||||
"chat_id": "1",
|
|
||||||
"id": "10",
|
|
||||||
"content": "Hello",
|
|
||||||
"account_id": "someflakeid",
|
|
||||||
"unread": false
|
|
||||||
},
|
|
||||||
"created_at": "somedate"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Streaming
|
|
||||||
|
|
||||||
There is an additional `user:pleroma_chat` stream. Incoming chat messages will make the current chat be sent to this `user` stream. The `event` of an incoming chat message is `pleroma:chat_update`. The payload is the updated chat with the incoming chat message in the `last_message` field.
|
|
||||||
|
|
||||||
### Web Push
|
|
||||||
|
|
||||||
If you want to receive push messages for this type, you'll need to add the `pleroma:chat_mention` type to your alerts in the push subscription.
|
|
|
@ -1,390 +0,0 @@
|
||||||
# Differences in Mastodon API responses from vanilla Mastodon
|
|
||||||
|
|
||||||
A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance`
|
|
||||||
|
|
||||||
## Flake IDs
|
|
||||||
|
|
||||||
Pleroma uses 128-bit ids as opposed to Mastodon's 64 bits. However, just like Mastodon's ids, they are lexically sortable strings
|
|
||||||
|
|
||||||
## Timelines
|
|
||||||
|
|
||||||
Adding the parameter `with_muted=true` to the timeline queries will also return activities by muted (not by blocked!) users.
|
|
||||||
|
|
||||||
Adding the parameter `exclude_visibilities` to the timeline queries will exclude the statuses with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`), e.g., `exclude_visibilities[]=direct&exclude_visibilities[]=private`.
|
|
||||||
|
|
||||||
Adding the parameter `reply_visibility` to the public and home timelines queries will filter replies. Possible values: without parameter (default) shows all replies, `following` - replies directed to you or users you follow, `self` - replies directed to you.
|
|
||||||
|
|
||||||
Adding the parameter `instance=lain.com` to the public timeline will show only statuses originating from `lain.com` (or any remote instance).
|
|
||||||
|
|
||||||
Home, public, hashtag & list timelines accept these parameters:
|
|
||||||
|
|
||||||
- `only_media`: show only statuses with media attached
|
|
||||||
- `local`: show only local statuses
|
|
||||||
- `remote`: show only remote statuses
|
|
||||||
|
|
||||||
## Statuses
|
|
||||||
|
|
||||||
- `visibility`: has additional possible values `list` and `local` (for local-only statuses)
|
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
|
||||||
|
|
||||||
- `local`: true if the post was made on the local instance
|
|
||||||
- `conversation_id`: the ID of the AP context the status is associated with (if any)
|
|
||||||
- `direct_conversation_id`: the ID of the Mastodon direct message conversation the status is associated with (if any)
|
|
||||||
- `in_reply_to_account_acct`: the `acct` property of User entity for replied user (if any)
|
|
||||||
- `content`: a map consisting of alternate representations of the `content` property with the key being its mimetype. Currently, the only alternate representation supported is `text/plain`
|
|
||||||
- `spoiler_text`: a map consisting of alternate representations of the `spoiler_text` property with the key being its mimetype. Currently, the only alternate representation supported is `text/plain`
|
|
||||||
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
|
|
||||||
- `thread_muted`: true if the thread the post belongs to is muted
|
|
||||||
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
|
|
||||||
- `parent_visible`: If the parent of this post is visible to the user or not.
|
|
||||||
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
|
|
||||||
|
|
||||||
The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes:
|
|
||||||
|
|
||||||
- `content_type`: The content type of the status source.
|
|
||||||
|
|
||||||
## Scheduled statuses
|
|
||||||
|
|
||||||
Has these additional fields in `params`:
|
|
||||||
|
|
||||||
- `expires_in`: the number of seconds the posted activity should expire in.
|
|
||||||
|
|
||||||
## Media Attachments
|
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
|
||||||
|
|
||||||
- `mime_type`: mime type of the attachment.
|
|
||||||
|
|
||||||
### Attachment cap
|
|
||||||
|
|
||||||
Some apps operate under the assumption that no more than 4 attachments can be returned or uploaded. Pleroma however does not enforce any limits on attachment count neither when returning the status object nor when posting.
|
|
||||||
|
|
||||||
### Limitations
|
|
||||||
|
|
||||||
Pleroma does not process remote images and therefore cannot include fields such as `meta` and `blurhash`. It does not support focal points or aspect ratios. The frontend is expected to handle it.
|
|
||||||
|
|
||||||
## Accounts
|
|
||||||
|
|
||||||
The `id` parameter can also be the `nickname` of the user. This only works in these endpoints, not the deeper nested ones for following etc.
|
|
||||||
|
|
||||||
- `/api/v1/accounts/:id`
|
|
||||||
- `/api/v1/accounts/:id/statuses`
|
|
||||||
|
|
||||||
`/api/v1/accounts/:id/statuses` endpoint accepts these parameters:
|
|
||||||
|
|
||||||
- `pinned`: include only pinned statuses
|
|
||||||
- `tagged`: with tag
|
|
||||||
- `only_media`: include only statuses with media attached
|
|
||||||
- `with_muted`: include statuses/reactions from muted accounts
|
|
||||||
- `exclude_reblogs`: exclude reblogs
|
|
||||||
- `exclude_replies`: exclude replies
|
|
||||||
- `exclude_visibilities`: exclude visibilities
|
|
||||||
|
|
||||||
Endpoints which accept `with_relationships` parameter:
|
|
||||||
|
|
||||||
- `/api/v1/accounts/:id`
|
|
||||||
- `/api/v1/accounts/:id/followers`
|
|
||||||
- `/api/v1/accounts/:id/following`
|
|
||||||
- `/api/v1/mutes`
|
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
|
||||||
|
|
||||||
- `ap_id`: nullable URL string, ActivityPub id of the user
|
|
||||||
- `background_image`: nullable URL string, background image of the user
|
|
||||||
- `tags`: Lists an array of tags for the user
|
|
||||||
- `relationship` (object): Includes fields as documented for Mastodon API https://docs.joinmastodon.org/entities/relationship/
|
|
||||||
- `is_moderator`: boolean, nullable, true if user is a moderator
|
|
||||||
- `is_admin`: boolean, nullable, true if user is an admin
|
|
||||||
- `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
|
|
||||||
- `hide_favorites`: boolean, true when the user has hiding favorites enabled
|
|
||||||
- `hide_followers`: boolean, true when the user has follower hiding enabled
|
|
||||||
- `hide_follows`: boolean, true when the user has follow hiding enabled
|
|
||||||
- `hide_followers_count`: boolean, true when the user has follower stat hiding enabled
|
|
||||||
- `hide_follows_count`: boolean, true when the user has follow stat hiding enabled
|
|
||||||
- `settings_store`: A generic map of settings for frontends. Opaque to the backend. Only returned in `/api/v1/accounts/verify_credentials` and `/api/v1/accounts/update_credentials`
|
|
||||||
- `chat_token`: The token needed for Pleroma shoutbox. Only returned in `/api/v1/accounts/verify_credentials`
|
|
||||||
- `deactivated`: boolean, true when the user is deactivated
|
|
||||||
- `allow_following_move`: boolean, true when the user allows automatically follow moved following accounts
|
|
||||||
- `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
|
|
||||||
- `unread_notifications_count`: The count of unread notifications. Only returned to the account owner.
|
|
||||||
- `notification_settings`: object, can be absent. See `/api/v1/pleroma/notification_settings` for the parameters/keys returned.
|
|
||||||
- `accepts_chat_messages`: boolean, but can be null if we don't have that information about a user
|
|
||||||
- `favicon`: nullable URL string, Favicon image of the user's instance
|
|
||||||
|
|
||||||
### Source
|
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
|
||||||
|
|
||||||
- `show_role`: boolean, nullable, true when the user wants his role (e.g admin, moderator) to be shown
|
|
||||||
- `no_rich_text` - boolean, nullable, true when html tags are stripped from all statuses requested from the API
|
|
||||||
- `discoverable`: boolean, true when the user allows external services (search bots) etc. to index / list the account (regardless of this setting, user will still appear in regular search results)
|
|
||||||
- `actor_type`: string, the type of this account.
|
|
||||||
|
|
||||||
## Conversations
|
|
||||||
|
|
||||||
Has an additional field under the `pleroma` object:
|
|
||||||
|
|
||||||
- `recipients`: The list of the recipients of this Conversation. These will be addressed when replying to this conversation.
|
|
||||||
|
|
||||||
## GET `/api/v1/conversations`
|
|
||||||
|
|
||||||
Accepts additional parameters:
|
|
||||||
|
|
||||||
- `recipients`: Only return conversations with the given recipients (a list of user ids). Usage example: `GET /api/v1/conversations?recipients[]=1&recipients[]=2`
|
|
||||||
|
|
||||||
## Account Search
|
|
||||||
|
|
||||||
Behavior has changed:
|
|
||||||
|
|
||||||
- `/api/v1/accounts/search`: Does not require authentication
|
|
||||||
|
|
||||||
## Search (global)
|
|
||||||
|
|
||||||
Unlisted posts are available in search results, they are considered to be public posts that shouldn't be shown in local/federated timeline.
|
|
||||||
|
|
||||||
## Notifications
|
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
|
||||||
|
|
||||||
- `is_seen`: true if the notification was read by the user
|
|
||||||
|
|
||||||
### Move Notification
|
|
||||||
|
|
||||||
The `type` value is `move`. Has an additional field:
|
|
||||||
|
|
||||||
- `target`: new account
|
|
||||||
|
|
||||||
### EmojiReact Notification
|
|
||||||
|
|
||||||
The `type` value is `pleroma:emoji_reaction`. Has these fields:
|
|
||||||
|
|
||||||
- `emoji`: The used emoji
|
|
||||||
- `account`: The account of the user who reacted
|
|
||||||
- `status`: The status that was reacted on
|
|
||||||
|
|
||||||
### ChatMention Notification (not default)
|
|
||||||
|
|
||||||
This notification has to be requested explicitly.
|
|
||||||
|
|
||||||
The `type` value is `pleroma:chat_mention`
|
|
||||||
|
|
||||||
- `account`: The account who sent the message
|
|
||||||
- `chat_message`: The chat message
|
|
||||||
|
|
||||||
### Report Notification (not default)
|
|
||||||
|
|
||||||
This notification has to be requested explicitly.
|
|
||||||
|
|
||||||
The `type` value is `pleroma:report`
|
|
||||||
|
|
||||||
- `account`: The account who reported
|
|
||||||
- `report`: The report
|
|
||||||
|
|
||||||
## GET `/api/v1/notifications`
|
|
||||||
|
|
||||||
Accepts additional parameters:
|
|
||||||
|
|
||||||
- `exclude_visibilities`: will exclude the notifications for activities with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`). Usage example: `GET /api/v1/notifications?exclude_visibilities[]=direct&exclude_visibilities[]=private`.
|
|
||||||
- `include_types`: will include the notifications for activities with the given types. The parameter accepts an array of types (`mention`, `follow`, `reblog`, `favourite`, `move`, `pleroma:emoji_reaction`, `pleroma:chat_mention`, `pleroma:report`). Usage example: `GET /api/v1/notifications?include_types[]=mention&include_types[]=reblog`.
|
|
||||||
|
|
||||||
## DELETE `/api/v1/notifications/destroy_multiple`
|
|
||||||
|
|
||||||
An endpoint to delete multiple statuses by IDs.
|
|
||||||
|
|
||||||
Required parameters:
|
|
||||||
|
|
||||||
- `ids`: array of activity ids
|
|
||||||
|
|
||||||
Usage example: `DELETE /api/v1/notifications/destroy_multiple/?ids[]=1&ids[]=2`.
|
|
||||||
|
|
||||||
Returns on success: 200 OK `{}`
|
|
||||||
|
|
||||||
## POST `/api/v1/statuses`
|
|
||||||
|
|
||||||
Additional parameters can be added to the JSON body/Form data:
|
|
||||||
|
|
||||||
- `preview`: boolean, if set to `true` the post won't be actually posted, but the status entity would still be rendered back. This could be useful for previewing rich text/custom emoji, for example.
|
|
||||||
- `content_type`: string, contain the MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint.
|
|
||||||
- `to`: A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for post visibility are not affected by this and will still apply.
|
|
||||||
- `visibility`: string, besides standard MastoAPI values (`direct`, `private`, `unlisted`, `local` or `public`) it can be used to address a List by setting it to `list:LIST_ID`.
|
|
||||||
- `expires_in`: The number of seconds the posted activity should expire in. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated. This needs to be longer than an hour.
|
|
||||||
- `in_reply_to_conversation_id`: Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`.
|
|
||||||
|
|
||||||
## GET `/api/v1/statuses`
|
|
||||||
|
|
||||||
An endpoint to get multiple statuses by IDs.
|
|
||||||
|
|
||||||
Required parameters:
|
|
||||||
|
|
||||||
- `ids`: array of activity ids
|
|
||||||
|
|
||||||
Usage example: `GET /api/v1/statuses/?ids[]=1&ids[]=2`.
|
|
||||||
|
|
||||||
Returns: array of Status.
|
|
||||||
|
|
||||||
The maximum number of statuses is limited to 100 per request.
|
|
||||||
|
|
||||||
## PATCH `/api/v1/accounts/update_credentials`
|
|
||||||
|
|
||||||
Additional parameters can be added to the JSON body/Form data:
|
|
||||||
|
|
||||||
- `no_rich_text` - if true, html tags are stripped from all statuses requested from the API
|
|
||||||
- `hide_followers` - if true, user's followers will be hidden
|
|
||||||
- `hide_follows` - if true, user's follows will be hidden
|
|
||||||
- `hide_followers_count` - if true, user's follower count will be hidden
|
|
||||||
- `hide_follows_count` - if true, user's follow count will be hidden
|
|
||||||
- `hide_favorites` - if true, user's favorites timeline will be hidden
|
|
||||||
- `show_role` - if true, user's role (e.g admin, moderator) will be exposed to anyone in the API
|
|
||||||
- `default_scope` - the scope returned under `privacy` key in Source subentity
|
|
||||||
- `pleroma_settings_store` - Opaque user settings to be saved on the backend.
|
|
||||||
- `skip_thread_containment` - if true, skip filtering out broken threads
|
|
||||||
- `allow_following_move` - if true, allows automatically follow moved following accounts
|
|
||||||
- `also_known_as` - array of ActivityPub IDs, needed for following move
|
|
||||||
- `pleroma_background_image` - sets the background image of the user. Can be set to "" (an empty string) to reset.
|
|
||||||
- `discoverable` - if true, external services (search bots) etc. are allowed to index / list the account (regardless of this setting, user will still appear in regular search results).
|
|
||||||
- `actor_type` - the type of this account.
|
|
||||||
- `accepts_chat_messages` - if false, this account will reject all chat messages.
|
|
||||||
- `language` - user's preferred language for receiving emails (digest, confirmation, etc.)
|
|
||||||
|
|
||||||
All images (avatar, banner and background) can be reset to the default by sending an empty string ("") instead of a file.
|
|
||||||
|
|
||||||
### Pleroma Settings Store
|
|
||||||
|
|
||||||
Pleroma has mechanism that allows frontends to save blobs of json for each user on the backend. This can be used to save frontend-specific settings for a user that the backend does not need to know about.
|
|
||||||
|
|
||||||
The parameter should have a form of `{frontend_name: {...}}`, with `frontend_name` identifying your type of client, e.g. `pleroma_fe`. It will overwrite everything under this property, but will not overwrite other frontend's settings.
|
|
||||||
|
|
||||||
This information is returned in the `/api/v1/accounts/verify_credentials` endpoint.
|
|
||||||
|
|
||||||
## Authentication
|
|
||||||
|
|
||||||
*Pleroma supports refreshing tokens.*
|
|
||||||
|
|
||||||
### POST `/oauth/token`
|
|
||||||
|
|
||||||
You can obtain access tokens for a user in a few additional ways.
|
|
||||||
|
|
||||||
#### Refreshing a token
|
|
||||||
|
|
||||||
To obtain a new access token from a refresh token, pass `grant_type=refresh_token` with the following extra parameters:
|
|
||||||
|
|
||||||
- `refresh_token`: The refresh token.
|
|
||||||
|
|
||||||
#### Getting a token with a password
|
|
||||||
|
|
||||||
To obtain a token from a user's password, pass `grant_type=password` with the following extra parameters:
|
|
||||||
|
|
||||||
- `username`: Username to authenticate.
|
|
||||||
- `password`: The user's password.
|
|
||||||
|
|
||||||
#### Response body
|
|
||||||
|
|
||||||
Additional fields are returned in the response:
|
|
||||||
|
|
||||||
- `id`: The primary key of this token in Pleroma's database.
|
|
||||||
- `me` (user tokens only): The ActivityPub ID of the user who owns the token.
|
|
||||||
|
|
||||||
## Account Registration
|
|
||||||
|
|
||||||
`POST /api/v1/accounts`
|
|
||||||
|
|
||||||
Has these additional parameters (which are the same as in Pleroma-API):
|
|
||||||
|
|
||||||
- `fullname`: optional
|
|
||||||
- `bio`: optional
|
|
||||||
- `captcha_solution`: optional, contains provider-specific captcha solution,
|
|
||||||
- `captcha_token`: optional, contains provider-specific captcha token
|
|
||||||
- `captcha_answer_data`: optional, contains provider-specific captcha data
|
|
||||||
- `token`: invite token required when the registrations aren't public.
|
|
||||||
- `language`: optional, user's preferred language for receiving emails (digest, confirmation, etc.), default to the language set in the `userLanguage` cookies or `Accept-Language` header.
|
|
||||||
|
|
||||||
## Instance
|
|
||||||
|
|
||||||
`GET /api/v1/instance` has additional fields
|
|
||||||
|
|
||||||
- `max_toot_chars`: The maximum characters per post
|
|
||||||
- `chat_limit`: The maximum characters per chat message
|
|
||||||
- `description_limit`: The maximum characters per image description
|
|
||||||
- `poll_limits`: The limits of polls
|
|
||||||
- `upload_limit`: The maximum upload file size
|
|
||||||
- `avatar_upload_limit`: The same for avatars
|
|
||||||
- `background_upload_limit`: The same for backgrounds
|
|
||||||
- `banner_upload_limit`: The same for banners
|
|
||||||
- `background_image`: A background image that frontends can use
|
|
||||||
- `pleroma.metadata.features`: A list of supported features
|
|
||||||
- `pleroma.metadata.federation`: The federation restrictions of this instance
|
|
||||||
- `pleroma.metadata.fields_limits`: A list of values detailing the length and count limitation for various instance-configurable fields.
|
|
||||||
- `pleroma.metadata.post_formats`: A list of the allowed post format types
|
|
||||||
- `vapid_public_key`: The public key needed for push messages
|
|
||||||
|
|
||||||
## Push Subscription
|
|
||||||
|
|
||||||
`POST /api/v1/push/subscription`
|
|
||||||
`PUT /api/v1/push/subscription`
|
|
||||||
|
|
||||||
Permits these additional alert types:
|
|
||||||
|
|
||||||
- pleroma:chat_mention
|
|
||||||
- pleroma:emoji_reaction
|
|
||||||
|
|
||||||
## Markers
|
|
||||||
|
|
||||||
Has these additional fields under the `pleroma` object:
|
|
||||||
|
|
||||||
- `unread_count`: contains number unread notifications
|
|
||||||
|
|
||||||
## Streaming
|
|
||||||
|
|
||||||
### Chats
|
|
||||||
|
|
||||||
There is an additional `user:pleroma_chat` stream. Incoming chat messages will make the current chat be sent to this `user` stream. The `event` of an incoming chat message is `pleroma:chat_update`. The payload is the updated chat with the incoming chat message in the `last_message` field.
|
|
||||||
|
|
||||||
### Remote timelines
|
|
||||||
|
|
||||||
For viewing remote server timelines, there are `public:remote` and `public:remote:media` streams. Each of these accept a parameter like `?instance=lain.com`.
|
|
||||||
|
|
||||||
### Follow relationships updates
|
|
||||||
|
|
||||||
Pleroma streams follow relationships updates as `pleroma:follow_relationships_update` events to the `user` stream.
|
|
||||||
|
|
||||||
The message payload consist of:
|
|
||||||
|
|
||||||
- `state`: a relationship state, one of `follow_pending`, `follow_accept` or `follow_reject`.
|
|
||||||
|
|
||||||
- `follower` and `following` maps with following fields:
|
|
||||||
- `id`: user ID
|
|
||||||
- `follower_count`: follower count
|
|
||||||
- `following_count`: following count
|
|
||||||
|
|
||||||
## User muting and thread muting
|
|
||||||
|
|
||||||
Both user muting and thread muting can be done for only a certain time by adding an `expires_in` parameter to the API calls and giving the expiration time in seconds.
|
|
||||||
|
|
||||||
## Not implemented
|
|
||||||
|
|
||||||
Pleroma is generally compatible with the Mastodon 2.7.2 API, but some newer features and non-essential features are omitted. These features usually return an HTTP 200 status code, but with an empty response. While they may be added in the future, they are considered low priority.
|
|
||||||
|
|
||||||
### Suggestions
|
|
||||||
|
|
||||||
*Added in Mastodon 2.4.3*
|
|
||||||
|
|
||||||
- `GET /api/v1/suggestions`: Returns an empty array, `[]`
|
|
||||||
|
|
||||||
### Trends
|
|
||||||
|
|
||||||
*Added in Mastodon 3.0.0*
|
|
||||||
|
|
||||||
- `GET /api/v1/trends`: Returns an empty array, `[]`
|
|
||||||
|
|
||||||
### Identity proofs
|
|
||||||
|
|
||||||
*Added in Mastodon 2.8.0*
|
|
||||||
|
|
||||||
- `GET /api/v1/identity_proofs`: Returns an empty array, `[]`
|
|
||||||
|
|
||||||
### Featured tags
|
|
||||||
|
|
||||||
*Added in Mastodon 3.0.0*
|
|
||||||
|
|
||||||
- `GET /api/v1/featured_tags`: Returns HTTP 404
|
|
|
@ -1,347 +0,0 @@
|
||||||
# Nodeinfo
|
|
||||||
|
|
||||||
See also [the Nodeinfo standard](https://nodeinfo.diaspora.software/).
|
|
||||||
|
|
||||||
## `/.well-known/nodeinfo`
|
|
||||||
### The well-known path
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params: none
|
|
||||||
* Response: JSON
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"links":[
|
|
||||||
{
|
|
||||||
"href":"https://example.com/nodeinfo/2.0.json",
|
|
||||||
"rel":"http://nodeinfo.diaspora.software/ns/schema/2.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"href":"https://example.com/nodeinfo/2.1.json",
|
|
||||||
"rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `/nodeinfo/2.0.json`
|
|
||||||
### Nodeinfo 2.0
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params: none
|
|
||||||
* Response: JSON
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"metadata":{
|
|
||||||
"accountActivationRequired":false,
|
|
||||||
"features":[
|
|
||||||
"pleroma_api",
|
|
||||||
"mastodon_api",
|
|
||||||
"mastodon_api_streaming",
|
|
||||||
"polls",
|
|
||||||
"pleroma_explicit_addressing",
|
|
||||||
"shareable_emoji_packs",
|
|
||||||
"multifetch",
|
|
||||||
"pleroma:api/v1/notifications:include_types_filter",
|
|
||||||
"chat",
|
|
||||||
"shout",
|
|
||||||
"relay",
|
|
||||||
"pleroma_emoji_reactions",
|
|
||||||
"pleroma_chat_messages"
|
|
||||||
],
|
|
||||||
"federation":{
|
|
||||||
"enabled":true,
|
|
||||||
"exclusions":false,
|
|
||||||
"mrf_hashtag":{
|
|
||||||
"federated_timeline_removal":[
|
|
||||||
|
|
||||||
],
|
|
||||||
"reject":[
|
|
||||||
|
|
||||||
],
|
|
||||||
"sensitive":[
|
|
||||||
"nsfw"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"mrf_object_age":{
|
|
||||||
"actions":[
|
|
||||||
"delist",
|
|
||||||
"strip_followers"
|
|
||||||
],
|
|
||||||
"threshold":604800
|
|
||||||
},
|
|
||||||
"mrf_policies":[
|
|
||||||
"ObjectAgePolicy",
|
|
||||||
"TagPolicy",
|
|
||||||
"HashtagPolicy"
|
|
||||||
],
|
|
||||||
"quarantined_instances":[
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"fieldsLimits":{
|
|
||||||
"maxFields":10,
|
|
||||||
"maxRemoteFields":20,
|
|
||||||
"nameLength":512,
|
|
||||||
"valueLength":2048
|
|
||||||
},
|
|
||||||
"invitesEnabled":false,
|
|
||||||
"mailerEnabled":false,
|
|
||||||
"nodeDescription":"Pleroma: An efficient and flexible fediverse server",
|
|
||||||
"nodeName":"Example",
|
|
||||||
"pollLimits":{
|
|
||||||
"max_expiration":31536000,
|
|
||||||
"max_option_chars":200,
|
|
||||||
"max_options":20,
|
|
||||||
"min_expiration":0
|
|
||||||
},
|
|
||||||
"postFormats":[
|
|
||||||
"text/plain",
|
|
||||||
"text/html",
|
|
||||||
"text/markdown",
|
|
||||||
"text/bbcode"
|
|
||||||
],
|
|
||||||
"private":false,
|
|
||||||
"restrictedNicknames":[
|
|
||||||
".well-known",
|
|
||||||
"~",
|
|
||||||
"about",
|
|
||||||
"activities",
|
|
||||||
"api",
|
|
||||||
"auth",
|
|
||||||
"check_password",
|
|
||||||
"dev",
|
|
||||||
"friend-requests",
|
|
||||||
"inbox",
|
|
||||||
"internal",
|
|
||||||
"main",
|
|
||||||
"media",
|
|
||||||
"nodeinfo",
|
|
||||||
"notice",
|
|
||||||
"oauth",
|
|
||||||
"objects",
|
|
||||||
"ostatus_subscribe",
|
|
||||||
"pleroma",
|
|
||||||
"proxy",
|
|
||||||
"push",
|
|
||||||
"registration",
|
|
||||||
"relay",
|
|
||||||
"settings",
|
|
||||||
"status",
|
|
||||||
"tag",
|
|
||||||
"user-search",
|
|
||||||
"user_exists",
|
|
||||||
"users",
|
|
||||||
"web",
|
|
||||||
"verify_credentials",
|
|
||||||
"update_credentials",
|
|
||||||
"relationships",
|
|
||||||
"search",
|
|
||||||
"confirmation_resend",
|
|
||||||
"mfa"
|
|
||||||
],
|
|
||||||
"skipThreadContainment":true,
|
|
||||||
"staffAccounts":[
|
|
||||||
"https://example.com/users/admin",
|
|
||||||
"https://example.com/users/staff"
|
|
||||||
],
|
|
||||||
"suggestions":{
|
|
||||||
"enabled":false
|
|
||||||
},
|
|
||||||
"uploadLimits":{
|
|
||||||
"avatar":2000000,
|
|
||||||
"background":4000000,
|
|
||||||
"banner":4000000,
|
|
||||||
"general":16000000
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openRegistrations":true,
|
|
||||||
"protocols":[
|
|
||||||
"activitypub"
|
|
||||||
],
|
|
||||||
"services":{
|
|
||||||
"inbound":[
|
|
||||||
|
|
||||||
],
|
|
||||||
"outbound":[
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"software":{
|
|
||||||
"name":"pleroma",
|
|
||||||
"version":"2.4.1"
|
|
||||||
},
|
|
||||||
"usage":{
|
|
||||||
"localPosts":27,
|
|
||||||
"users":{
|
|
||||||
"activeHalfyear":129,
|
|
||||||
"activeMonth":70,
|
|
||||||
"total":235
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"version":"2.0"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `/nodeinfo/2.1.json`
|
|
||||||
### Nodeinfo 2.1
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params: none
|
|
||||||
* Response: JSON
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"metadata":{
|
|
||||||
"accountActivationRequired":false,
|
|
||||||
"features":[
|
|
||||||
"pleroma_api",
|
|
||||||
"mastodon_api",
|
|
||||||
"mastodon_api_streaming",
|
|
||||||
"polls",
|
|
||||||
"pleroma_explicit_addressing",
|
|
||||||
"shareable_emoji_packs",
|
|
||||||
"multifetch",
|
|
||||||
"pleroma:api/v1/notifications:include_types_filter",
|
|
||||||
"chat",
|
|
||||||
"shout",
|
|
||||||
"relay",
|
|
||||||
"pleroma_emoji_reactions",
|
|
||||||
"pleroma_chat_messages"
|
|
||||||
],
|
|
||||||
"federation":{
|
|
||||||
"enabled":true,
|
|
||||||
"exclusions":false,
|
|
||||||
"mrf_hashtag":{
|
|
||||||
"federated_timeline_removal":[
|
|
||||||
|
|
||||||
],
|
|
||||||
"reject":[
|
|
||||||
|
|
||||||
],
|
|
||||||
"sensitive":[
|
|
||||||
"nsfw"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"mrf_object_age":{
|
|
||||||
"actions":[
|
|
||||||
"delist",
|
|
||||||
"strip_followers"
|
|
||||||
],
|
|
||||||
"threshold":604800
|
|
||||||
},
|
|
||||||
"mrf_policies":[
|
|
||||||
"ObjectAgePolicy",
|
|
||||||
"TagPolicy",
|
|
||||||
"HashtagPolicy"
|
|
||||||
],
|
|
||||||
"quarantined_instances":[
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"fieldsLimits":{
|
|
||||||
"maxFields":10,
|
|
||||||
"maxRemoteFields":20,
|
|
||||||
"nameLength":512,
|
|
||||||
"valueLength":2048
|
|
||||||
},
|
|
||||||
"invitesEnabled":false,
|
|
||||||
"mailerEnabled":false,
|
|
||||||
"nodeDescription":"Pleroma: An efficient and flexible fediverse server",
|
|
||||||
"nodeName":"Example",
|
|
||||||
"pollLimits":{
|
|
||||||
"max_expiration":31536000,
|
|
||||||
"max_option_chars":200,
|
|
||||||
"max_options":20,
|
|
||||||
"min_expiration":0
|
|
||||||
},
|
|
||||||
"postFormats":[
|
|
||||||
"text/plain",
|
|
||||||
"text/html",
|
|
||||||
"text/markdown",
|
|
||||||
"text/bbcode"
|
|
||||||
],
|
|
||||||
"private":false,
|
|
||||||
"restrictedNicknames":[
|
|
||||||
".well-known",
|
|
||||||
"~",
|
|
||||||
"about",
|
|
||||||
"activities",
|
|
||||||
"api",
|
|
||||||
"auth",
|
|
||||||
"check_password",
|
|
||||||
"dev",
|
|
||||||
"friend-requests",
|
|
||||||
"inbox",
|
|
||||||
"internal",
|
|
||||||
"main",
|
|
||||||
"media",
|
|
||||||
"nodeinfo",
|
|
||||||
"notice",
|
|
||||||
"oauth",
|
|
||||||
"objects",
|
|
||||||
"ostatus_subscribe",
|
|
||||||
"pleroma",
|
|
||||||
"proxy",
|
|
||||||
"push",
|
|
||||||
"registration",
|
|
||||||
"relay",
|
|
||||||
"settings",
|
|
||||||
"status",
|
|
||||||
"tag",
|
|
||||||
"user-search",
|
|
||||||
"user_exists",
|
|
||||||
"users",
|
|
||||||
"web",
|
|
||||||
"verify_credentials",
|
|
||||||
"update_credentials",
|
|
||||||
"relationships",
|
|
||||||
"search",
|
|
||||||
"confirmation_resend",
|
|
||||||
"mfa"
|
|
||||||
],
|
|
||||||
"skipThreadContainment":true,
|
|
||||||
"staffAccounts":[
|
|
||||||
"https://example.com/users/admin",
|
|
||||||
"https://example.com/users/staff"
|
|
||||||
],
|
|
||||||
"suggestions":{
|
|
||||||
"enabled":false
|
|
||||||
},
|
|
||||||
"uploadLimits":{
|
|
||||||
"avatar":2000000,
|
|
||||||
"background":4000000,
|
|
||||||
"banner":4000000,
|
|
||||||
"general":16000000
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"openRegistrations":true,
|
|
||||||
"protocols":[
|
|
||||||
"activitypub"
|
|
||||||
],
|
|
||||||
"services":{
|
|
||||||
"inbound":[
|
|
||||||
|
|
||||||
],
|
|
||||||
"outbound":[
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"software":{
|
|
||||||
"name":"pleroma",
|
|
||||||
"repository":"https://git.pleroma.social/pleroma/pleroma",
|
|
||||||
"version":"2.4.1"
|
|
||||||
},
|
|
||||||
"usage":{
|
|
||||||
"localPosts":27,
|
|
||||||
"users":{
|
|
||||||
"activeHalfyear":129,
|
|
||||||
"activeMonth":70,
|
|
||||||
"total":235
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"version":"2.1"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,766 +0,0 @@
|
||||||
# Pleroma API
|
|
||||||
|
|
||||||
Requests that require it can be authenticated with [an OAuth token](https://tools.ietf.org/html/rfc6749), the `_pleroma_key` cookie, or [HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization).
|
|
||||||
|
|
||||||
Request parameters can be passed via [query strings](https://en.wikipedia.org/wiki/Query_string) or as [form data](https://www.w3.org/TR/html401/interact/forms.html). Files must be uploaded as `multipart/form-data`.
|
|
||||||
|
|
||||||
The `/api/v1/pleroma/*` path is backwards compatible with `/api/pleroma/*` (`/api/pleroma/*` will be deprecated in the future).
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/emoji`
|
|
||||||
### Lists the custom emoji on that server.
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params: none
|
|
||||||
* Response: JSON
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"girlpower": {
|
|
||||||
"tags": [
|
|
||||||
"Finmoji"
|
|
||||||
],
|
|
||||||
"image_url": "/finmoji/128px/girlpower-128.png"
|
|
||||||
},
|
|
||||||
"education": {
|
|
||||||
"tags": [
|
|
||||||
"Finmoji"
|
|
||||||
],
|
|
||||||
"image_url": "/finmoji/128px/education-128.png"
|
|
||||||
},
|
|
||||||
"finnishlove": {
|
|
||||||
"tags": [
|
|
||||||
"Finmoji"
|
|
||||||
],
|
|
||||||
"image_url": "/finmoji/128px/finnishlove-128.png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Note: Same data as Mastodon API’s `/api/v1/custom_emojis` but in a different format
|
|
||||||
|
|
||||||
## `/api/pleroma/follow_import`
|
|
||||||
### Imports your follows, for example from a Mastodon CSV file.
|
|
||||||
* Method: `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `list`: STRING or FILE containing a whitespace-separated list of accounts to follow
|
|
||||||
* Response: HTTP 200 on success, 500 on error
|
|
||||||
* Note: Users that can't be followed are silently skipped.
|
|
||||||
|
|
||||||
## `/api/pleroma/blocks_import`
|
|
||||||
### Imports your blocks.
|
|
||||||
* Method: `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `list`: STRING or FILE containing a whitespace-separated list of accounts to block
|
|
||||||
* Response: HTTP 200 on success, 500 on error
|
|
||||||
|
|
||||||
## `/api/pleroma/mutes_import`
|
|
||||||
### Imports your mutes.
|
|
||||||
* Method: `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `list`: STRING or FILE containing a whitespace-separated list of accounts to mute
|
|
||||||
* Response: HTTP 200 on success, 500 on error
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/captcha`
|
|
||||||
### Get a new captcha
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params: none
|
|
||||||
* Response: Provider specific JSON, the only guaranteed parameter is `type`
|
|
||||||
* Example response: `{"type": "kocaptcha", "token": "whatever", "url": "https://captcha.kotobank.ch/endpoint", "seconds_valid": 300}`
|
|
||||||
|
|
||||||
## `/api/pleroma/delete_account`
|
|
||||||
### Delete an account
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `password`: user's password
|
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the deletion was successful, `{"error": "[error message]"}` otherwise
|
|
||||||
* Example response: `{"error": "Invalid password."}`
|
|
||||||
|
|
||||||
## `/api/pleroma/disable_account`
|
|
||||||
### Disable an account
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `password`: user's password
|
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the account was successfully disabled, `{"error": "[error message]"}` otherwise
|
|
||||||
* Example response: `{"error": "Invalid password."}`
|
|
||||||
|
|
||||||
## `/api/pleroma/accounts/mfa`
|
|
||||||
#### Gets current MFA settings
|
|
||||||
* method: `GET`
|
|
||||||
* Authentication: required
|
|
||||||
* OAuth scope: `read:security`
|
|
||||||
* Response: JSON. Returns `{"settings": {"enabled": "false", "totp": false }}`
|
|
||||||
* Note: `enabled` is whether multi-factor auth is enabled for the user in general, while `totp` is one type of MFA.
|
|
||||||
|
|
||||||
## `/api/pleroma/accounts/mfa/setup/totp`
|
|
||||||
#### Pre-setup the MFA/TOTP method
|
|
||||||
* method: `GET`
|
|
||||||
* Authentication: required
|
|
||||||
* OAuth scope: `write:security`
|
|
||||||
* Response: JSON. Returns `{"key": [secret_key], "provisioning_uri": "[qr code uri]" }` when successful, otherwise returns HTTP 422 `{"error": "error_msg"}`
|
|
||||||
|
|
||||||
## `/api/pleroma/accounts/mfa/confirm/totp`
|
|
||||||
#### Confirms & enables MFA/TOTP support for user account.
|
|
||||||
* method: `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* OAuth scope: `write:security`
|
|
||||||
* Params:
|
|
||||||
* `password`: user's password
|
|
||||||
* `code`: token from TOTP App
|
|
||||||
* Response: JSON. Returns `{}` if the enable was successful, HTTP 422 `{"error": "[error message]"}` otherwise
|
|
||||||
|
|
||||||
|
|
||||||
## `/api/pleroma/accounts/mfa/totp`
|
|
||||||
#### Disables MFA/TOTP method for user account.
|
|
||||||
* method: `DELETE`
|
|
||||||
* Authentication: required
|
|
||||||
* OAuth scope: `write:security`
|
|
||||||
* Params:
|
|
||||||
* `password`: user's password
|
|
||||||
* Response: JSON. Returns `{}` if the disable was successful, HTTP 422 `{"error": "[error message]"}` otherwise
|
|
||||||
* Example response: `{"error": "Invalid password."}`
|
|
||||||
|
|
||||||
## `/api/pleroma/accounts/mfa/backup_codes`
|
|
||||||
#### Generstes backup codes MFA for user account.
|
|
||||||
* method: `GET`
|
|
||||||
* Authentication: required
|
|
||||||
* OAuth scope: `write:security`
|
|
||||||
* Response: JSON. Returns `{"codes": codes}`when successful, otherwise HTTP 422 `{"error": "[error message]"}`
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/admin/`
|
|
||||||
See [Admin-API](admin_api.md)
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/notifications/read`
|
|
||||||
### Mark notifications as read
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params (mutually exclusive):
|
|
||||||
* `id`: a single notification id to read
|
|
||||||
* `max_id`: read all notifications up to this id
|
|
||||||
* Response: Notification entity/Array of Notification entities that were read. In case of `max_id`, only the first 80 read notifications will be returned.
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/accounts/:id/subscribe`
|
|
||||||
### Subscribe to receive notifications for all statuses posted by a user
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `id`: account id to subscribe to
|
|
||||||
* Response: JSON, returns a mastodon relationship object on success, otherwise returns `{"error": "error_msg"}`
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "abcdefg",
|
|
||||||
"following": true,
|
|
||||||
"followed_by": false,
|
|
||||||
"blocking": false,
|
|
||||||
"muting": false,
|
|
||||||
"muting_notifications": false,
|
|
||||||
"subscribing": true,
|
|
||||||
"notifying": true,
|
|
||||||
"requested": false,
|
|
||||||
"domain_blocking": false,
|
|
||||||
"showing_reblogs": true,
|
|
||||||
"endorsed": false,
|
|
||||||
"note": ""
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/accounts/:id/unsubscribe`
|
|
||||||
### Unsubscribe to stop receiving notifications from user statuses
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `id`: account id to unsubscribe from
|
|
||||||
* Response: JSON, returns a mastodon relationship object on success, otherwise returns `{"error": "error_msg"}`
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "abcdefg",
|
|
||||||
"following": true,
|
|
||||||
"followed_by": false,
|
|
||||||
"blocking": false,
|
|
||||||
"muting": false,
|
|
||||||
"muting_notifications": false,
|
|
||||||
"subscribing": false,
|
|
||||||
"notifying": false,
|
|
||||||
"requested": false,
|
|
||||||
"domain_blocking": false,
|
|
||||||
"showing_reblogs": true,
|
|
||||||
"endorsed": false,
|
|
||||||
"note": ""
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/accounts/:id/favourites`
|
|
||||||
### Returns favorites timeline of any user
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params:
|
|
||||||
* `id`: the id of the account for whom to return results
|
|
||||||
* `limit`: optional, the number of records to retrieve
|
|
||||||
* `since_id`: optional, returns results that are more recent than the specified id
|
|
||||||
* `max_id`: optional, returns results that are older than the specified id
|
|
||||||
* Response: JSON, returns a list of Mastodon Status entities on success, otherwise returns `{"error": "error_msg"}`
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"account": {
|
|
||||||
"id": "9hptFmUF3ztxYh3Svg",
|
|
||||||
"url": "https://pleroma.example.org/users/nick2",
|
|
||||||
"username": "nick2",
|
|
||||||
...
|
|
||||||
},
|
|
||||||
"application": {"name": "Web", "website": null},
|
|
||||||
"bookmarked": false,
|
|
||||||
"card": null,
|
|
||||||
"content": "This is :moominmamma: note 0",
|
|
||||||
"created_at": "2019-04-15T15:42:15.000Z",
|
|
||||||
"emojis": [],
|
|
||||||
"favourited": false,
|
|
||||||
"favourites_count": 1,
|
|
||||||
"id": "9hptFmVJ02khbzYJaS",
|
|
||||||
"in_reply_to_account_id": null,
|
|
||||||
"in_reply_to_id": null,
|
|
||||||
"language": null,
|
|
||||||
"media_attachments": [],
|
|
||||||
"mentions": [],
|
|
||||||
"muted": false,
|
|
||||||
"pinned": false,
|
|
||||||
"pleroma": {
|
|
||||||
"content": {"text/plain": "This is :moominmamma: note 0"},
|
|
||||||
"conversation_id": 13679,
|
|
||||||
"local": true,
|
|
||||||
"spoiler_text": {"text/plain": "2hu"}
|
|
||||||
},
|
|
||||||
"reblog": null,
|
|
||||||
"reblogged": false,
|
|
||||||
"reblogs_count": 0,
|
|
||||||
"replies_count": 0,
|
|
||||||
"sensitive": false,
|
|
||||||
"spoiler_text": "2hu",
|
|
||||||
"tags": [{"name": "2hu", "url": "/tag/2hu"}],
|
|
||||||
"uri": "https://pleroma.example.org/objects/198ed2a1-7912-4482-b559-244a0369e984",
|
|
||||||
"url": "https://pleroma.example.org/notice/9hptFmVJ02khbzYJaS",
|
|
||||||
"visibility": "public"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/accounts/update_*`
|
|
||||||
### Set and clear account avatar, banner, and background
|
|
||||||
|
|
||||||
- PATCH `/api/v1/pleroma/accounts/update_avatar`: Set/clear user avatar image
|
|
||||||
- PATCH `/api/v1/pleroma/accounts/update_banner`: Set/clear user banner image
|
|
||||||
- PATCH `/api/v1/pleroma/accounts/update_background`: Set/clear user background image
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/accounts/confirmation_resend`
|
|
||||||
### Resend confirmation email
|
|
||||||
* Method `POST`
|
|
||||||
* Params:
|
|
||||||
* `email`: email of that needs to be verified
|
|
||||||
* Authentication: not required
|
|
||||||
* Response: 204 No Content
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/mascot`
|
|
||||||
### Gets user mascot image
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: required
|
|
||||||
|
|
||||||
* Response: JSON. Returns a mastodon media attachment entity.
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "abcdefg",
|
|
||||||
"url": "https://pleroma.example.org/media/abcdefg.png",
|
|
||||||
"type": "image",
|
|
||||||
"pleroma": {
|
|
||||||
"mime_type": "image/png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Updates user mascot image
|
|
||||||
* Method `PUT`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `file`: Multipart image
|
|
||||||
* Response: JSON. Returns a mastodon media attachment entity
|
|
||||||
when successful, otherwise returns HTTP 415 `{"error": "error_msg"}`
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "abcdefg",
|
|
||||||
"url": "https://pleroma.example.org/media/abcdefg.png",
|
|
||||||
"type": "image",
|
|
||||||
"pleroma": {
|
|
||||||
"mime_type": "image/png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Note: Behaves exactly the same as `POST /api/v1/upload`.
|
|
||||||
Can only accept images - any attempt to upload non-image files will be met with `HTTP 415 Unsupported Media Type`.
|
|
||||||
|
|
||||||
## `/api/pleroma/notification_settings`
|
|
||||||
### Updates user notification settings
|
|
||||||
* Method `PUT`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `block_from_strangers`: BOOLEAN field, blocks notifications from accounts you do not follow
|
|
||||||
* `hide_notification_contents`: BOOLEAN field. When set to true, it removes the contents of a message from the push notification.
|
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the update was successful, otherwise returns `{"error": "error_msg"}`
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/healthcheck`
|
|
||||||
### Healthcheck endpoint with additional system data.
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params: none
|
|
||||||
* Response: JSON, statuses (200 - healthy, 503 unhealthy).
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"pool_size": 0, # database connection pool
|
|
||||||
"active": 0, # active processes
|
|
||||||
"idle": 0, # idle processes
|
|
||||||
"memory_used": 0.00, # Memory used
|
|
||||||
"healthy": true, # Instance state
|
|
||||||
"job_queue_stats": {} # Job queue stats
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `/api/pleroma/change_email`
|
|
||||||
### Change account email
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `password`: user's password
|
|
||||||
* `email`: new email
|
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
|
||||||
* Note: Currently, Mastodon has no API for changing email. If they add it in future it might be incompatible with Pleroma.
|
|
||||||
|
|
||||||
## `/api/pleroma/move_account`
|
|
||||||
### Move account
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `password`: user's password
|
|
||||||
* `target_account`: the nickname of the target account (e.g. `foo@example.org`)
|
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
|
||||||
* Note: This endpoint emits a `Move` activity to all followers of the current account. Some remote servers will automatically unfollow the current account and follow the target account upon seeing this, but this depends on the remote server implementation and cannot be guaranteed. For local followers , they will automatically unfollow and follow if and only if they have set the `allow_following_move` preference ("Allow auto-follow when following account moves").
|
|
||||||
|
|
||||||
## `/api/pleroma/aliases`
|
|
||||||
### Get aliases of the current account
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: required
|
|
||||||
* Response: JSON. Returns `{"aliases": [alias, ...]}`, where `alias` is the nickname of an alias, e.g. `foo@example.org`.
|
|
||||||
|
|
||||||
### Add alias to the current account
|
|
||||||
* Method `PUT`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `alias`: the nickname of the alias to add, e.g. `foo@example.org`.
|
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
|
||||||
|
|
||||||
### Delete alias from the current account
|
|
||||||
* Method `DELETE`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `alias`: the nickname of the alias to delete, e.g. `foo@example.org`.
|
|
||||||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
|
||||||
|
|
||||||
# Pleroma Conversations
|
|
||||||
|
|
||||||
Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints:
|
|
||||||
|
|
||||||
1. Pleroma Conversations never add or remove recipients, unless explicitly changed by the user.
|
|
||||||
2. Pleroma Conversations statuses can be requested by Conversation id.
|
|
||||||
3. Pleroma Conversations can be replied to.
|
|
||||||
|
|
||||||
Conversations have the additional field `recipients` under the `pleroma` key. This holds a list of all the accounts that will receive a message in this conversation.
|
|
||||||
|
|
||||||
The status posting endpoint takes an additional parameter, `in_reply_to_conversation_id`, which, when set, will set the visiblity to direct and address only the people who are the recipients of that Conversation.
|
|
||||||
|
|
||||||
⚠ Conversation IDs can be found in direct messages with the `pleroma.direct_conversation_id` key, do not confuse it with `pleroma.conversation_id`.
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/conversations/:id/statuses`
|
|
||||||
### Timeline for a given conversation
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: required
|
|
||||||
* Params: Like other timelines
|
|
||||||
* Response: JSON, statuses (200 - healthy, 503 unhealthy).
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/conversations/:id`
|
|
||||||
### The conversation with the given ID.
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: required
|
|
||||||
* Params: None
|
|
||||||
* Response: JSON, statuses (200 - healthy, 503 unhealthy).
|
|
||||||
|
|
||||||
## `PATCH /api/v1/pleroma/conversations/:id`
|
|
||||||
### Update a conversation. Used to change the set of recipients.
|
|
||||||
* Method `PATCH`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `recipients`: A list of ids of users that should receive posts to this conversation. This will replace the current list of recipients, so submit the full list. The owner of owner of the conversation will always be part of the set of recipients, though.
|
|
||||||
* Response: JSON, statuses (200 - healthy, 503 unhealthy)
|
|
||||||
|
|
||||||
## `POST /api/v1/pleroma/conversations/read`
|
|
||||||
### Marks all user's conversations as read.
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params: None
|
|
||||||
* Response: JSON, returns a list of Mastodon Conversation entities that were marked as read (200 - healthy, 503 unhealthy).
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/emoji/pack?name=:name`
|
|
||||||
|
|
||||||
### Get pack.json for the pack
|
|
||||||
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params:
|
|
||||||
* `page`: page number for files (default 1)
|
|
||||||
* `page_size`: page size for files (default 30)
|
|
||||||
* Response: JSON, pack json with `files`, `files_count` and `pack` keys with 200 status or 404 if the pack does not exist.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"files": {...},
|
|
||||||
"files_count": 0, // emoji count in pack
|
|
||||||
"pack": {...}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `POST /api/v1/pleroma/emoji/pack?name=:name`
|
|
||||||
|
|
||||||
### Creates an empty pack
|
|
||||||
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params:
|
|
||||||
* `name`: pack name
|
|
||||||
* Response: JSON, "ok" and 200 status or 409 if the pack with that name already exists
|
|
||||||
|
|
||||||
## `PATCH /api/v1/pleroma/emoji/pack?name=:name`
|
|
||||||
|
|
||||||
### Updates (replaces) pack metadata
|
|
||||||
|
|
||||||
* Method `PATCH`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params:
|
|
||||||
* `name`: pack name
|
|
||||||
* `metadata`: metadata to replace the old one
|
|
||||||
* `license`: Pack license
|
|
||||||
* `homepage`: Pack home page url
|
|
||||||
* `description`: Pack description
|
|
||||||
* `fallback-src`: Fallback url to download pack from
|
|
||||||
* `fallback-src-sha256`: SHA256 encoded for fallback pack archive
|
|
||||||
* `share-files`: is pack allowed for sharing (boolean)
|
|
||||||
* Response: JSON, updated "metadata" section of the pack and 200 status or 400 if there was a
|
|
||||||
problem with the new metadata (the error is specified in the "error" part of the response JSON)
|
|
||||||
|
|
||||||
## `DELETE /api/v1/pleroma/emoji/pack?name=:name`
|
|
||||||
|
|
||||||
### Delete a custom emoji pack
|
|
||||||
|
|
||||||
* Method `DELETE`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params:
|
|
||||||
* `name`: pack name
|
|
||||||
* Response: JSON, "ok" and 200 status or 500 if there was an error deleting the pack
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/emoji/packs/import`
|
|
||||||
|
|
||||||
### Imports packs from filesystem
|
|
||||||
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params: None
|
|
||||||
* Response: JSON, returns a list of imported packs.
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/emoji/packs/remote`
|
|
||||||
|
|
||||||
### Make request to another instance for packs list
|
|
||||||
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params:
|
|
||||||
* `url`: url of the instance to get packs from
|
|
||||||
* `page`: page number for packs (default 1)
|
|
||||||
* `page_size`: page size for packs (default 50)
|
|
||||||
* Response: JSON with the pack list, hashmap with pack name and pack contents
|
|
||||||
|
|
||||||
## `POST /api/v1/pleroma/emoji/packs/download`
|
|
||||||
|
|
||||||
### Download pack from another instance
|
|
||||||
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params:
|
|
||||||
* `url`: url of the instance to download from
|
|
||||||
* `name`: pack to download from that instance
|
|
||||||
* `as`: (*optional*) name how to save pack
|
|
||||||
* Response: JSON, "ok" with 200 status if the pack was downloaded, or 500 if there were
|
|
||||||
errors downloading the pack
|
|
||||||
|
|
||||||
## `POST /api/v1/pleroma/emoji/packs/files?name=:name`
|
|
||||||
|
|
||||||
### Add new file to the pack
|
|
||||||
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params:
|
|
||||||
* `name`: pack name
|
|
||||||
* `file`: file needs to be uploaded with the multipart request or link to remote file.
|
|
||||||
* `shortcode`: (*optional*) shortcode for new emoji, must be unique for all emoji. If not sended, shortcode will be taken from original filename.
|
|
||||||
* `filename`: (*optional*) new emoji file name. If not specified will be taken from original filename.
|
|
||||||
* Response: JSON, list of files for updated pack (hashmap -> shortcode => filename) with status 200, either error status with error message.
|
|
||||||
|
|
||||||
## `PATCH /api/v1/pleroma/emoji/packs/files?name=:name`
|
|
||||||
|
|
||||||
### Update emoji file from pack
|
|
||||||
|
|
||||||
* Method `PATCH`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params:
|
|
||||||
* `name`: pack name
|
|
||||||
* `shortcode`: emoji file shortcode
|
|
||||||
* `new_shortcode`: new emoji file shortcode
|
|
||||||
* `new_filename`: new filename for emoji file
|
|
||||||
* `force`: (*optional*) with true value to overwrite existing emoji with new shortcode
|
|
||||||
* Response: JSON, list with updated files for updated pack (hashmap -> shortcode => filename) with status 200, either error status with error message.
|
|
||||||
|
|
||||||
## `DELETE /api/v1/pleroma/emoji/packs/files?name=:name`
|
|
||||||
|
|
||||||
### Delete emoji file from pack
|
|
||||||
|
|
||||||
* Method `DELETE`
|
|
||||||
* Authentication: required (admin)
|
|
||||||
* Params:
|
|
||||||
* `name`: pack name
|
|
||||||
* `shortcode`: emoji file shortcode
|
|
||||||
* Response: JSON, list with updated files for updated pack (hashmap -> shortcode => filename) with status 200, either error status with error message.
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/emoji/packs`
|
|
||||||
|
|
||||||
### Lists local custom emoji packs
|
|
||||||
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params:
|
|
||||||
* `page`: page number for packs (default 1)
|
|
||||||
* `page_size`: page size for packs (default 50)
|
|
||||||
* Response: `packs` key with JSON hashmap of pack name to pack contents and `count` key for count of packs.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"packs": {
|
|
||||||
"pack_name": {...}, // pack contents
|
|
||||||
...
|
|
||||||
},
|
|
||||||
"count": 0 // packs count
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/emoji/packs/archive?name=:name`
|
|
||||||
|
|
||||||
### Requests a local pack archive from the instance
|
|
||||||
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params:
|
|
||||||
* `name`: pack name
|
|
||||||
* Response: the archive of the pack with a 200 status code, 403 if the pack is not set as shared,
|
|
||||||
404 if the pack does not exist
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/accounts/:id/scrobbles`
|
|
||||||
### Requests a list of current and recent Listen activities for an account
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params: None
|
|
||||||
* Response: An array of media metadata entities.
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"account": {...},
|
|
||||||
"id": "1234",
|
|
||||||
"title": "Some Title",
|
|
||||||
"artist": "Some Artist",
|
|
||||||
"album": "Some Album",
|
|
||||||
"length": 180000,
|
|
||||||
"created_at": "2019-09-28T12:40:45.000Z"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## `POST /api/v1/pleroma/scrobble`
|
|
||||||
### Creates a new Listen activity for an account
|
|
||||||
* Method `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params:
|
|
||||||
* `title`: the title of the media playing
|
|
||||||
* `album`: the album of the media playing [optional]
|
|
||||||
* `artist`: the artist of the media playing [optional]
|
|
||||||
* `length`: the length of the media playing [optional]
|
|
||||||
* Response: the newly created media metadata entity representing the Listen activity
|
|
||||||
|
|
||||||
# Emoji Reactions
|
|
||||||
|
|
||||||
Emoji reactions work a lot like favourites do. They make it possible to react to a post with a single emoji character. To detect the presence of this feature, you can check `pleroma_emoji_reactions` entry in the features list of nodeinfo.
|
|
||||||
|
|
||||||
## `PUT /api/v1/pleroma/statuses/:id/reactions/:emoji`
|
|
||||||
### React to a post with a unicode emoji
|
|
||||||
* Method: `PUT`
|
|
||||||
* Authentication: required
|
|
||||||
* Params: `emoji`: A unicode RGI emoji or a regional indicator
|
|
||||||
* Response: JSON, the status.
|
|
||||||
|
|
||||||
## `DELETE /api/v1/pleroma/statuses/:id/reactions/:emoji`
|
|
||||||
### Remove a reaction to a post with a unicode emoji
|
|
||||||
* Method: `DELETE`
|
|
||||||
* Authentication: required
|
|
||||||
* Params: `emoji`: A unicode RGI emoji or a regional indicator
|
|
||||||
* Response: JSON, the status.
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/statuses/:id/reactions`
|
|
||||||
### Get an object of emoji to account mappings with accounts that reacted to the post
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: optional
|
|
||||||
* Params: None
|
|
||||||
* Response: JSON, a list of emoji/account list tuples, sorted by emoji insertion date, in ascending order, e.g, the first emoji in the list is the oldest.
|
|
||||||
* Example Response:
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{"name": "😀", "count": 2, "me": true, "accounts": [{"id" => "xyz.."...}, {"id" => "zyx..."}]},
|
|
||||||
{"name": "☕", "count": 1, "me": false, "accounts": [{"id" => "abc..."}]}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/statuses/:id/reactions/:emoji`
|
|
||||||
### Get an object of emoji to account mappings with accounts that reacted to the post for a specific emoji
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: optional
|
|
||||||
* Params: None
|
|
||||||
* Response: JSON, a list of emoji/account list tuples
|
|
||||||
* Example Response:
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{"name": "😀", "count": 2, "me": true, "accounts": [{"id" => "xyz.."...}, {"id" => "zyx..."}]}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## `POST /api/v1/pleroma/backups`
|
|
||||||
### Create a user backup archive
|
|
||||||
|
|
||||||
* Method: `POST`
|
|
||||||
* Authentication: required
|
|
||||||
* Params: none
|
|
||||||
* Response: JSON
|
|
||||||
* Example response:
|
|
||||||
|
|
||||||
```json
|
|
||||||
[{
|
|
||||||
"content_type": "application/zip",
|
|
||||||
"file_size": 0,
|
|
||||||
"inserted_at": "2020-09-10T16:18:03.000Z",
|
|
||||||
"processed": false,
|
|
||||||
"url": "https://example.com/media/backups/archive-foobar-20200910T161803-QUhx6VYDRQ2wfV0SdA2Pfj_2CLM_ATUlw-D5l5TJf4Q.zip"
|
|
||||||
}]
|
|
||||||
```
|
|
||||||
|
|
||||||
## `GET /api/v1/pleroma/backups`
|
|
||||||
### Lists user backups
|
|
||||||
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: not required
|
|
||||||
* Params: none
|
|
||||||
* Response: JSON
|
|
||||||
* Example response:
|
|
||||||
|
|
||||||
```json
|
|
||||||
[{
|
|
||||||
"content_type": "application/zip",
|
|
||||||
"file_size": 55457,
|
|
||||||
"inserted_at": "2020-09-10T16:18:03.000Z",
|
|
||||||
"processed": true,
|
|
||||||
"url": "https://example.com/media/backups/archive-foobar-20200910T161803-QUhx6VYDRQ2wfV0SdA2Pfj_2CLM_ATUlw-D5l5TJf4Q.zip"
|
|
||||||
}]
|
|
||||||
```
|
|
||||||
|
|
||||||
## `GET /api/oauth_tokens`
|
|
||||||
### Retrieve a list of active sessions for the user
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: required
|
|
||||||
* Params: none
|
|
||||||
* Response: JSON
|
|
||||||
* Example response:
|
|
||||||
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"app_name": "Pleroma FE",
|
|
||||||
"id": 9275,
|
|
||||||
"valid_until": "2121-11-24T15:51:08.234234"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"app_name": "Patron",
|
|
||||||
"id": 8805,
|
|
||||||
"valid_until": "2121-10-26T18:09:59.857150"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"app_name": "Soapbox FE",
|
|
||||||
"id": 9727,
|
|
||||||
"valid_until": "2121-12-25T16:52:39.692877"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## `DELETE /api/oauth_tokens/:id`
|
|
||||||
### Revoke a user session by its ID
|
|
||||||
* Method: `DELETE`
|
|
||||||
* Authentication: required
|
|
||||||
* Params: none
|
|
||||||
* Response: HTTP 200 on success, 500 on error
|
|
||||||
|
|
||||||
## `/api/v1/pleroma/settings/:app`
|
|
||||||
### Gets settings for some application
|
|
||||||
* Method `GET`
|
|
||||||
* Authentication: `read:accounts`
|
|
||||||
|
|
||||||
* Response: JSON. The settings for that application, or empty object if there is none.
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"some key": "some value"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Updates settings for some application
|
|
||||||
* Method `PATCH`
|
|
||||||
* Authentication: `write:accounts`
|
|
||||||
* Request body: JSON object. The object will be merged recursively with old settings. If some field is set to null, it is removed.
|
|
||||||
* Example request:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"some key": "some value",
|
|
||||||
"key to remove": null,
|
|
||||||
"nested field": {
|
|
||||||
"some key": "some value",
|
|
||||||
"key to remove": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
* Response: JSON. Updated (merged) settings for that application.
|
|
||||||
* Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"some key": "some value",
|
|
||||||
"nested field": {
|
|
||||||
"some key": "some value",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,44 +0,0 @@
|
||||||
# Prometheus Metrics
|
|
||||||
|
|
||||||
Pleroma includes support for exporting metrics via the [prometheus_ex](https://github.com/deadtrickster/prometheus.ex) library.
|
|
||||||
|
|
||||||
Config example:
|
|
||||||
|
|
||||||
```
|
|
||||||
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter,
|
|
||||||
enabled: true,
|
|
||||||
auth: {:basic, "myusername", "mypassword"},
|
|
||||||
ip_whitelist: ["127.0.0.1"],
|
|
||||||
path: "/api/pleroma/app_metrics",
|
|
||||||
format: :text
|
|
||||||
```
|
|
||||||
|
|
||||||
* `enabled` (Pleroma extension) enables the endpoint
|
|
||||||
* `ip_whitelist` (Pleroma extension) could be used to restrict access only to specified IPs
|
|
||||||
* `auth` sets the authentication (`false` for no auth; configurable to HTTP Basic Auth, see [prometheus-plugs](https://github.com/deadtrickster/prometheus-plugs#exporting) documentation)
|
|
||||||
* `format` sets the output format (`:text` or `:protobuf`)
|
|
||||||
* `path` sets the path to app metrics page
|
|
||||||
|
|
||||||
|
|
||||||
## `/api/pleroma/app_metrics`
|
|
||||||
|
|
||||||
### Exports Prometheus application metrics
|
|
||||||
|
|
||||||
* Method: `GET`
|
|
||||||
* Authentication: not required by default (see configuration options above)
|
|
||||||
* Params: none
|
|
||||||
* Response: text
|
|
||||||
|
|
||||||
## Grafana
|
|
||||||
|
|
||||||
### Config example
|
|
||||||
|
|
||||||
The following is a config example to use with [Grafana](https://grafana.com)
|
|
||||||
|
|
||||||
```
|
|
||||||
- job_name: 'beam'
|
|
||||||
metrics_path: /api/pleroma/app_metrics
|
|
||||||
scheme: https
|
|
||||||
static_configs:
|
|
||||||
- targets: ['pleroma.soykaf.com']
|
|
||||||
```
|
|
|
@ -1,65 +0,0 @@
|
||||||
# AP Extensions
|
|
||||||
## Actor endpoints
|
|
||||||
|
|
||||||
The following endpoints are additionally present into our actors.
|
|
||||||
|
|
||||||
- `oauthRegistrationEndpoint` (`http://litepub.social/ns#oauthRegistrationEndpoint`)
|
|
||||||
- `uploadMedia` (`https://www.w3.org/ns/activitystreams#uploadMedia`)
|
|
||||||
|
|
||||||
### oauthRegistrationEndpoint
|
|
||||||
|
|
||||||
Points to MastodonAPI `/api/v1/apps` for now.
|
|
||||||
|
|
||||||
See <https://docs.joinmastodon.org/methods/apps/>
|
|
||||||
|
|
||||||
### uploadMedia
|
|
||||||
|
|
||||||
Inspired by <https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload>, it is part of the ActivityStreams namespace because it used to be part of the ActivityPub specification and got removed from it.
|
|
||||||
|
|
||||||
Content-Type: multipart/form-data
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
- (required) `file`: The file being uploaded
|
|
||||||
- (optionnal) `description`: A plain-text description of the media, for accessibility purposes.
|
|
||||||
|
|
||||||
Response: HTTP 201 Created with the object into the body, no `Location` header provided as it doesn't have an `id`
|
|
||||||
|
|
||||||
The object given in the reponse should then be inserted into an Object's `attachment` field.
|
|
||||||
|
|
||||||
## ChatMessages
|
|
||||||
|
|
||||||
`ChatMessage`s are the messages sent in 1-on-1 chats. They are similar to
|
|
||||||
`Note`s, but the addresing is done by having a single AP actor in the `to`
|
|
||||||
field. Addressing multiple actors is not allowed. These messages are always
|
|
||||||
private, there is no public version of them. They are created with a `Create`
|
|
||||||
activity.
|
|
||||||
|
|
||||||
They are part of the `litepub` namespace as `http://litepub.social/ns#ChatMessage`.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"actor": "http://2hu.gensokyo/users/raymoo",
|
|
||||||
"id": "http://2hu.gensokyo/objects/1",
|
|
||||||
"object": {
|
|
||||||
"attributedTo": "http://2hu.gensokyo/users/raymoo",
|
|
||||||
"content": "You expected a cute girl? Too bad.",
|
|
||||||
"id": "http://2hu.gensokyo/objects/2",
|
|
||||||
"published": "2020-02-12T14:08:20Z",
|
|
||||||
"to": [
|
|
||||||
"http://2hu.gensokyo/users/marisa"
|
|
||||||
],
|
|
||||||
"type": "ChatMessage"
|
|
||||||
},
|
|
||||||
"published": "2018-02-12T14:08:20Z",
|
|
||||||
"to": [
|
|
||||||
"http://2hu.gensokyo/users/marisa"
|
|
||||||
],
|
|
||||||
"type": "Create"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This setup does not prevent multi-user chats, but these will have to go through
|
|
||||||
a `Group`, which will be the recipient of the messages and then `Announce` them
|
|
||||||
to the users in the `Group`.
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Authentication & Authorization
|
|
||||||
|
|
||||||
## OAuth token-based authentication & authorization
|
|
||||||
|
|
||||||
* Pleroma supports hierarchical OAuth scopes, just like Mastodon but with added granularity of admin scopes. For a reference, see [Mastodon OAuth scopes](https://docs.joinmastodon.org/api/oauth-scopes/).
|
|
||||||
|
|
||||||
* It is important to either define OAuth scope restrictions or explicitly mark OAuth scope check as skipped, for every controller action. To define scopes, call `plug(Pleroma.Web.Plugs.OAuthScopesPlug, %{scopes: [...]})`. To explicitly set OAuth scopes check skipped, call `plug(:skip_plug, Pleroma.Web.Plugs.OAuthScopesPlug <when ...>)`.
|
|
||||||
|
|
||||||
* In controllers, `use Pleroma.Web, :controller` will result in `action/2` (see `Pleroma.Web.controller/0` for definition) be called prior to actual controller action, and it'll perform security / privacy checks before passing control to actual controller action.
|
|
||||||
|
|
||||||
For routes with `:authenticated_api` pipeline, authentication & authorization are expected, thus `OAuthScopesPlug` will be run unless explicitly skipped (also `EnsureAuthenticatedPlug` will be executed immediately before action even if there was an early run to give an early error, since `OAuthScopesPlug` supports `:proceed_unauthenticated` option, and other plugs may support similar options as well).
|
|
||||||
|
|
||||||
For `:api` pipeline routes, it'll be verified whether `OAuthScopesPlug` was called or explicitly skipped, and if it was not then auth information will be dropped for request. Then `EnsurePublicOrAuthenticatedPlug` will be called to ensure that either the instance is not private or user is authenticated (unless explicitly skipped). Such automated checks help to prevent human errors and result in higher security / privacy for users.
|
|
||||||
|
|
||||||
## Non-OAuth authentication
|
|
||||||
|
|
||||||
* With non-OAuth authentication ([HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) or HTTP header- or params-provided auth), OAuth scopes check is _not_ performed for any action (since password is provided during the auth, requester is able to obtain a token with full permissions anyways); auth plugs invoke `Pleroma.Helpers.AuthHelper.skip_oauth(conn)` in this case.
|
|
||||||
|
|
||||||
## Auth-related configuration, OAuth consumer mode etc.
|
|
||||||
|
|
||||||
See `Authentication` section of [the configuration cheatsheet](../configuration/cheatsheet.md#authentication).
|
|
|
@ -1 +0,0 @@
|
||||||
This section contains notes and guidelines for developers.
|
|
|
@ -1,9 +0,0 @@
|
||||||
# Setting up a Gitlab-runner
|
|
||||||
|
|
||||||
When you push changes, a pipeline will start some automated jobs. These are done with so called [runners](https://docs.gitlab.com/runner/), services that run somewhere on a server and run these automated jobs. These jobs typically run tests and should pass. If not, you probably need to fix something.
|
|
||||||
|
|
||||||
Generally, Pleroma provides a runner, so you don't need to set up your own. However, if for whatever reason you want to set up your own, here's some high level instructions.
|
|
||||||
|
|
||||||
1. We use docker to run the jobs, so you should install that. For Debian, you need to allow non-free packages in the [source list](https://wiki.debian.org/SourcesList). Then you can install docker with `apt install docker-compose`.
|
|
||||||
2. You can [install](https://docs.gitlab.com/runner/install/index.html) and [configure](https://docs.gitlab.com/runner/register/index.html) a Gitlab-runner. It's probably easiest to install from the packages, but there are other options as well.
|
|
||||||
3. When registering the runner, you'll need some values. You can find them in the project under your own name. Choose "Settings", "CI/CD", and then expand "Runners". For executor you can choose "docker". For default image, you can use the image used in <https://git.pleroma.social/pleroma/pleroma/-/blob/develop/.gitlab-ci.yml#L1> (although it shouldn't matter much).
|
|
|
@ -1,70 +0,0 @@
|
||||||
# Setting up a Pleroma development environment
|
|
||||||
|
|
||||||
Pleroma requires some adjustments from the defaults for running the instance locally. The following should help you to get started.
|
|
||||||
|
|
||||||
## Installing
|
|
||||||
|
|
||||||
1. Install Pleroma as explained in [the docs](../installation/debian_based_en.md), with some exceptions:
|
|
||||||
* You can use your own fork of the repository and add pleroma as a remote `git remote add pleroma 'https://git.pleroma.social/pleroma/pleroma'`
|
|
||||||
* You can skip systemd and nginx and all that stuff
|
|
||||||
* No need to create a dedicated pleroma user, it's easier to just use your own user
|
|
||||||
* For the DB you can still choose a dedicated user, the mix tasks set it up for you so it's no extra work for you
|
|
||||||
* For domain you can use `localhost`
|
|
||||||
* instead of creating a `prod.secret.exs`, create `dev.secret.exs`
|
|
||||||
* No need to prefix with `MIX_ENV=prod`. We're using dev and that's the default MIX_ENV
|
|
||||||
2. Change the dev.secret.exs
|
|
||||||
* Change the scheme in `config :pleroma, Pleroma.Web.Endpoint` to http (see examples below)
|
|
||||||
* If you want to change other settings, you can do that too
|
|
||||||
3. You can now start the server `mix phx.server`. Once it's build and started, you can access the instance on `http://<host>:<port>` (e.g.http://localhost:4000 ) and should be able to do everything locally you normaly can.
|
|
||||||
|
|
||||||
Example config to change the scheme to http. Change the port if you want to run on another port.
|
|
||||||
```elixir
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
|
||||||
url: [host: "localhost", scheme: "http", port: 4000],
|
|
||||||
```
|
|
||||||
|
|
||||||
Example config to disable captcha. This makes it a bit easier to create test-users.
|
|
||||||
```elixir
|
|
||||||
config :pleroma, Pleroma.Captcha,
|
|
||||||
enabled: false
|
|
||||||
```
|
|
||||||
|
|
||||||
Example config to change the log level to info
|
|
||||||
```elixir
|
|
||||||
config :logger, :console,
|
|
||||||
# :debug :info :warning :error
|
|
||||||
level: :info
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
1. Create a `test.secret.exs` file with the content as shown below
|
|
||||||
2. Create the database user and test database.
|
|
||||||
1. You can use the `config/setup_db.psql` as a template. Copy the file if you want and change the database name, user and password to the values for the test-database (e.g. 'pleroma_local_test' for database and user). Then run this file like you did during installation.
|
|
||||||
2. The tests will try to create the Database, so we'll have to allow our test-database user to create databases, `sudo -Hu postgres psql -c "ALTER USER pleroma_local_test WITH CREATEDB;"`
|
|
||||||
3. Run the tests with `mix test`. The tests should succeed.
|
|
||||||
|
|
||||||
Example content for the `test.secret.exs` file. Feel free to use another user, database name or password, just make sure the database is dedicated for the testing environment.
|
|
||||||
```elixir
|
|
||||||
# Pleroma test configuration
|
|
||||||
|
|
||||||
# NOTE: This file should not be committed to a repo or otherwise made public
|
|
||||||
# without removing sensitive information.
|
|
||||||
|
|
||||||
import Config
|
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
|
||||||
username: "pleroma_local_test",
|
|
||||||
password: "mysuperduperpassword",
|
|
||||||
database: "pleroma_local_test",
|
|
||||||
hostname: "localhost"
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Updating
|
|
||||||
|
|
||||||
Update Pleroma as explained in [the docs](../administration/updating.md). Just make sure you pull from upstream and not from your own fork.
|
|
||||||
|
|
||||||
## Working on multiple branches
|
|
||||||
|
|
||||||
If you develop on a separate branch, it's possible you did migrations that aren't merged into another branch you're working on. If you have multiple things you're working on, it's probably best to set up multiple pleroma's each with their own database. If you finished with a branch and want to switch back to develop to start a new branch from there, you can drop the database and recreate the database (e.g. by using `config/setup_db.psql`). The commands to drop and recreate the database can be found in [the docs](../administration/backup.md).
|
|
|
@ -1,19 +0,0 @@
|
||||||
# Introduction to Pleroma
|
|
||||||
## What is Pleroma?
|
|
||||||
Pleroma is a federated social networking platform, compatible with Mastodon and other ActivityPub implementations. It is free software licensed under the AGPLv3.
|
|
||||||
It actually consists of two components: a backend, named simply Pleroma, and a user-facing frontend, named Pleroma-FE. It also includes the Mastodon frontend, if that's your thing.
|
|
||||||
It's part of what we call the fediverse, a federated network of instances which speak common protocols and can communicate with each other.
|
|
||||||
One account on an instance is enough to talk to the entire fediverse!
|
|
||||||
|
|
||||||
## How can I use it?
|
|
||||||
|
|
||||||
Pleroma instances are already widely deployed, a list can be found at <https://the-federation.info/pleroma> and <https://fediverse.network/pleroma>.
|
|
||||||
|
|
||||||
If you don't feel like joining an existing instance, but instead prefer to deploy your own instance, that's easy too!
|
|
||||||
Installation instructions can be found in the installation section of these docs.
|
|
||||||
|
|
||||||
## I got an account, now what?
|
|
||||||
Great! Now you can explore the fediverse! Open the login page for your Pleroma instance (e.g. <https://pleroma.soykaf.com>) and login with your username and password. (If you don't have an account yet, click on Register)
|
|
||||||
|
|
||||||
### Pleroma-FE
|
|
||||||
The default front-end used by Pleroma is Pleroma-FE. You can find more information on what it is and how to use it in the [Introduction to Pleroma-FE](../frontend).
|
|
|
@ -1,21 +1,29 @@
|
||||||
# Installing on Alpine Linux
|
# Installing on Alpine Linux
|
||||||
|
|
||||||
{! backend/installation/otp_vs_from_source_source.include !}
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
This guide is a step-by-step installation guide for Alpine Linux. The instructions were verified against Alpine v3.10 standard image. You might miss additional dependencies if you use `netboot` instead.
|
This guide is a step-by-step installation guide for Alpine Linux. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.linode.com/docs/tools-reference/custom-kernels-distros/install-alpine-linux-on-your-linode/#configuration). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su -l <username> -s $SHELL -c 'command'` instead.
|
||||||
|
|
||||||
It assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.linode.com/docs/tools-reference/custom-kernels-distros/install-alpine-linux-on-your-linode/#configuration). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su -l <username> -s $SHELL -c 'command'` instead.
|
### Required packages
|
||||||
|
|
||||||
{! backend/installation/generic_dependencies.include !}
|
* `postgresql`
|
||||||
|
* `elixir`
|
||||||
|
* `erlang`
|
||||||
|
* `erlang-parsetools`
|
||||||
|
* `erlang-xmerl`
|
||||||
|
* `git`
|
||||||
|
* Development Tools
|
||||||
|
|
||||||
|
#### Optional packages used in this guide
|
||||||
|
|
||||||
|
* `nginx` (preferred, example configs for other reverse proxies can be found in the repo)
|
||||||
|
* `certbot` (or any other ACME client for Let’s Encrypt certificates)
|
||||||
|
|
||||||
### Prepare the system
|
### Prepare the system
|
||||||
|
|
||||||
* The community repository must be enabled in `/etc/apk/repositories`. Depending on which version and mirror you use this looks like `http://alpine.42.fr/v3.10/community`. If you autogenerated the mirror during installation:
|
* First make sure to have the community repository enabled:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
awk 'NR==2' /etc/apk/repositories | sed 's/main/community/' | tee -a /etc/apk/repositories
|
echo "https://nl.alpinelinux.org/alpine/latest-stable/community" | sudo tee -a /etc/apk/repository
|
||||||
```
|
```
|
||||||
|
|
||||||
* Then update the system, if not already done:
|
* Then update the system, if not already done:
|
||||||
|
@ -28,7 +36,7 @@ sudo apk upgrade
|
||||||
* Install some tools, which are needed later:
|
* Install some tools, which are needed later:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo apk add git build-base cmake file-dev
|
sudo apk add git build-base
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install Elixir and Erlang
|
### Install Elixir and Erlang
|
||||||
|
@ -44,7 +52,6 @@ sudo apk add erlang erlang-runtime-tools erlang-xmerl elixir
|
||||||
```shell
|
```shell
|
||||||
sudo apk add erlang-eldap
|
sudo apk add erlang-eldap
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install PostgreSQL
|
### Install PostgreSQL
|
||||||
|
|
||||||
* Install Postgresql server:
|
* Install Postgresql server:
|
||||||
|
@ -65,19 +72,12 @@ sudo /etc/init.d/postgresql start
|
||||||
sudo rc-update add postgresql
|
sudo rc-update add postgresql
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install media / graphics packages (optional, see [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md))
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo apk add ffmpeg imagemagick exiftool
|
|
||||||
```
|
|
||||||
|
|
||||||
### Install PleromaBE
|
### Install PleromaBE
|
||||||
|
|
||||||
* Add a new system user for the Pleroma service:
|
* Add a new system user for the Pleroma service:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo addgroup pleroma
|
sudo adduser -S -s /bin/false -h /opt/pleroma -H pleroma
|
||||||
sudo adduser -S -s /bin/false -h /opt/pleroma -H -G pleroma pleroma
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: To execute a single command as the Pleroma system user, use `sudo -Hu pleroma command`. You can also switch to a shell by using `sudo -Hu pleroma $SHELL`. If you don’t have and want `sudo` on your system, you can use `su` as root user (UID 0) for a single command by using `su -l pleroma -s $SHELL -c 'command'` and `su -l pleroma -s $SHELL` for starting a shell.
|
**Note**: To execute a single command as the Pleroma system user, use `sudo -Hu pleroma command`. You can also switch to a shell by using `sudo -Hu pleroma $SHELL`. If you don’t have and want `sudo` on your system, you can use `su` as root user (UID 0) for a single command by using `su -l pleroma -s $SHELL -c 'command'` and `su -l pleroma -s $SHELL` for starting a shell.
|
||||||
|
@ -102,7 +102,7 @@ cd /opt/pleroma
|
||||||
sudo -Hu pleroma mix deps.get
|
sudo -Hu pleroma mix deps.get
|
||||||
```
|
```
|
||||||
|
|
||||||
* Generate the configuration: `sudo -Hu pleroma MIX_ENV=prod mix pleroma.instance gen`
|
* Generate the configuration: `sudo -Hu pleroma mix pleroma.instance gen`
|
||||||
* Answer with `yes` if it asks you to install `rebar3`.
|
* Answer with `yes` if it asks you to install `rebar3`.
|
||||||
* This may take some time, because parts of pleroma get compiled first.
|
* This may take some time, because parts of pleroma get compiled first.
|
||||||
* After that it will ask you a few questions about your instance and generates a configuration file in `config/generated_config.exs`.
|
* After that it will ask you a few questions about your instance and generates a configuration file in `config/generated_config.exs`.
|
||||||
|
@ -110,7 +110,7 @@ sudo -Hu pleroma mix deps.get
|
||||||
* Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances):
|
* Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs}
|
mv config/{generated_config.exs,prod.secret.exs}
|
||||||
```
|
```
|
||||||
|
|
||||||
* The previous command creates also the file `config/setup_db.psql`, with which you can create the database:
|
* The previous command creates also the file `config/setup_db.psql`, with which you can create the database:
|
||||||
|
@ -164,26 +164,7 @@ If that doesn’t work, make sure, that nginx is not already running. If it stil
|
||||||
sudo cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/conf.d/pleroma.conf
|
sudo cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/conf.d/pleroma.conf
|
||||||
```
|
```
|
||||||
|
|
||||||
* Before starting nginx edit the configuration and change it to your needs. You must change change `server_name` and the paths to the certificates. You can use `nano` (install with `apk add nano` if missing).
|
* Before starting nginx edit the configuration and change it to your needs (e.g. change servername, change cert paths)
|
||||||
|
|
||||||
```
|
|
||||||
server {
|
|
||||||
server_name your.domain;
|
|
||||||
listen 80;
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
server_name your.domain;
|
|
||||||
listen 443 ssl http2;
|
|
||||||
...
|
|
||||||
ssl_trusted_certificate /etc/letsencrypt/live/your.domain/chain.pem;
|
|
||||||
ssl_certificate /etc/letsencrypt/live/your.domain/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/your.domain/privkey.pem;
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* Enable and start nginx:
|
* Enable and start nginx:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
@ -221,8 +202,14 @@ sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress
|
||||||
|
|
||||||
#### Further reading
|
#### Further reading
|
||||||
|
|
||||||
{! backend/installation/further_reading.include !}
|
* [Admin tasks](Admin tasks)
|
||||||
|
* [Backup your instance](Backup-your-instance)
|
||||||
|
* [Configuration tips](General tips for customizing pleroma fe)
|
||||||
|
* [Hardening your instance](Hardening-your-instance)
|
||||||
|
* [How to activate mediaproxy](How-to-activate-mediaproxy)
|
||||||
|
* [Small Pleroma-FE customizations](Small customizations)
|
||||||
|
* [Updating your instance](Updating-your-instance)
|
||||||
|
|
||||||
## Questions
|
## Questions
|
||||||
|
|
||||||
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:libera.chat](https://matrix.to/#/#pleroma:libera.chat) via Matrix or **#pleroma** on **libera.chat** via IRC.
|
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**.
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
# Installing on Arch Linux
|
# Installing on Arch Linux
|
||||||
|
|
||||||
{! backend/installation/otp_vs_from_source_source.include !}
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
This guide will assume that you have administrative rights, either as root or a user with [sudo permissions](https://wiki.archlinux.org/index.php/Sudo). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
|
This guide will assume that you have administrative rights, either as root or a user with [sudo permissions](https://wiki.archlinux.org/index.php/Sudo). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
|
||||||
|
@ -12,16 +9,11 @@ This guide will assume that you have administrative rights, either as root or a
|
||||||
* `elixir`
|
* `elixir`
|
||||||
* `git`
|
* `git`
|
||||||
* `base-devel`
|
* `base-devel`
|
||||||
* `cmake`
|
|
||||||
* `file`
|
|
||||||
|
|
||||||
#### Optional packages used in this guide
|
#### Optional packages used in this guide
|
||||||
|
|
||||||
* `nginx` (preferred, example configs for other reverse proxies can be found in the repo)
|
* `nginx` (preferred, example configs for other reverse proxies can be found in the repo)
|
||||||
* `certbot` (or any other ACME client for Let’s Encrypt certificates)
|
* `certbot` (or any other ACME client for Let’s Encrypt certificates)
|
||||||
* `ImageMagick`
|
|
||||||
* `ffmpeg`
|
|
||||||
* `exiftool`
|
|
||||||
|
|
||||||
### Prepare the system
|
### Prepare the system
|
||||||
|
|
||||||
|
@ -34,7 +26,7 @@ sudo pacman -Syu
|
||||||
* Install some of the above mentioned programs:
|
* Install some of the above mentioned programs:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo pacman -S git base-devel elixir cmake file
|
sudo pacman -S git base-devel elixir
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install PostgreSQL
|
### Install PostgreSQL
|
||||||
|
@ -59,12 +51,6 @@ sudo -iu postgres initdb -D /var/lib/postgres/data
|
||||||
sudo systemctl enable --now postgresql.service
|
sudo systemctl enable --now postgresql.service
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install media / graphics packages (optional, see [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md))
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo pacman -S ffmpeg imagemagick perl-image-exiftool
|
|
||||||
```
|
|
||||||
|
|
||||||
### Install PleromaBE
|
### Install PleromaBE
|
||||||
|
|
||||||
* Add a new system user for the Pleroma service:
|
* Add a new system user for the Pleroma service:
|
||||||
|
@ -95,7 +81,7 @@ cd /opt/pleroma
|
||||||
sudo -Hu pleroma mix deps.get
|
sudo -Hu pleroma mix deps.get
|
||||||
```
|
```
|
||||||
|
|
||||||
* Generate the configuration: `sudo -Hu pleroma MIX_ENV=prod mix pleroma.instance gen`
|
* Generate the configuration: `sudo -Hu pleroma mix pleroma.instance gen`
|
||||||
* Answer with `yes` if it asks you to install `rebar3`.
|
* Answer with `yes` if it asks you to install `rebar3`.
|
||||||
* This may take some time, because parts of pleroma get compiled first.
|
* This may take some time, because parts of pleroma get compiled first.
|
||||||
* After that it will ask you a few questions about your instance and generates a configuration file in `config/generated_config.exs`.
|
* After that it will ask you a few questions about your instance and generates a configuration file in `config/generated_config.exs`.
|
||||||
|
@ -103,7 +89,7 @@ sudo -Hu pleroma mix deps.get
|
||||||
* Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances):
|
* Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs}
|
mv config/{generated_config.exs,prod.secret.exs}
|
||||||
```
|
```
|
||||||
|
|
||||||
* The previous command creates also the file `config/setup_db.psql`, with which you can create the database:
|
* The previous command creates also the file `config/setup_db.psql`, with which you can create the database:
|
||||||
|
@ -214,8 +200,14 @@ sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new <username> <your@emailaddress
|
||||||
|
|
||||||
#### Further reading
|
#### Further reading
|
||||||
|
|
||||||
{! backend/installation/further_reading.include !}
|
* [Admin tasks](Admin tasks)
|
||||||
|
* [Backup your instance](Backup-your-instance)
|
||||||
|
* [Configuration tips](General tips for customizing pleroma fe)
|
||||||
|
* [Hardening your instance](Hardening-your-instance)
|
||||||
|
* [How to activate mediaproxy](How-to-activate-mediaproxy)
|
||||||
|
* [Small Pleroma-FE customizations](Small customizations)
|
||||||
|
* [Updating your instance](Updating-your-instance)
|
||||||
|
|
||||||
## Questions
|
## Questions
|
||||||
|
|
||||||
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:libera.chat](https://matrix.to/#/#pleroma:libera.chat) via Matrix or **#pleroma** on **libera.chat** via IRC.
|
Questions about the installation or didn’t it work as it should be, ask in [#pleroma:matrix.org](https://matrix.heldscal.la/#/room/#freenode_#pleroma:matrix.org) or IRC Channel **#pleroma** on **Freenode**.
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue