Merge branch 'master' into sidekiq-redis

This commit is contained in:
Andy Piper 2023-12-07 13:52:11 +00:00 committed by GitHub
commit ba6ee0f2f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
96 changed files with 2044 additions and 709 deletions

27
.github/workflows/rebase-needed.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: PR Needs Rebase
on:
schedule:
- cron: '0 * * * *'
permissions:
pull-requests: write
jobs:
label-rebase-needed:
runs-on: ubuntu-latest
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Check for merge conflicts
uses: eps1lon/actions-label-merge-conflict@releases/2.x
with:
dirtyLabel: 'rebase needed :construction:'
repoToken: '${{ secrets.GITHUB_TOKEN }}'
commentOnClean: This pull request has resolved merge conflicts and is ready for review.
commentOnDirty: This pull request has merge conflicts that must be resolved before it can be merged.
retryMax: 30
continueOnMissingPermissions: false

View File

@ -1,4 +1,9 @@
![Mastodon](https://i.imgur.com/NhZc40l.png)
====
<h1><picture>
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/mastodon/mastodon/raw/main/lib/assets/wordmark.dark.png?raw=true">
<source media="(prefers-color-scheme: light)" srcset="https://github.com/mastodon/mastodon/raw/main/lib/assets/wordmark.light.png?raw=true">
<img alt="Mastodon" src="https://github.com/mastodon/mastodon/raw/mainlib/assets/wordmark.light.png?raw=true" height="34">
</picture></h1>
The documentation currently uses Hugo to generate a static site from Markdown.
View the documentation at <https://docs.joinmastodon.org>

View File

@ -38,14 +38,14 @@ Authorization
**Internal parameter.** Use HTTP `Link` header for pagination.
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 20 statuses or 40 accounts. Max twice the default limit.

View File

@ -205,12 +205,13 @@ Determines the amount of logs generated by Mastodon. Defaults to `info`, which g
Tells the Mastodon web and streaming processes which IPs act as your trusted reverse proxy (e.g. nginx, Cloudflare). It affects how Mastodon determines the source IP of each request, which is used for important rate limits and security functions. If the value is set incorrectly then Mastodon could use the IP of the reverse proxy instead of the actual source.
By default the loopback and private network address ranges are trusted. Specifically:
* `127.0.0.1/8`
* `::1/128`
* `10.0.0.0/8`
* `172.16.0.0/12`
* `192.168.0.0/16`
* `fc00::/7`
- `127.0.0.1/8`
- `::1/128`
- `10.0.0.0/8`
- `172.16.0.0/12`
- `192.168.0.0/16`
- `fc00::/7`
If you're using a single reverse proxy and it runs on the same machine or is in the same private network as your Mastodon web and streaming processes then you most likely don't need to modify this setting and can use the default. Or if you're using multiple reverse proxy servers and they're all in the same private network as your Mastodon web and streaming processes then, again, the default should be fine. However, if you're using a reverse proxy server that reaches your Mastodon web and streaming servers via a public IP address (for example if you're using Cloudflare or a similar proxy) then you'll need to set this variable. It should be the IPs of all reverse proxies in use, as a comma-separated list of IPs or IP ranges using [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation). Note that when this variable is set the default ranges (mentioned above) will no longer be trusted, so if you have both an external reverse proxy _and_ a proxy on localhost then you must include the IPs (or IP ranges) of both.
@ -276,7 +277,11 @@ The streaming API can be deployed to a different domain/subdomain. This may impr
Example value: `wss://streaming.example.com`
#### `STREAMING_CLUSTER_NUM`
#### `STREAMING_CLUSTER_NUM` (deprecated) {#streaming_cluster_num}
{{< hint style="danger" >}}
Deprecated: The streaming server process now only uses a single node.js process, to scale it further, you'll need to follow the documentation in the [scaling guide](/admin/scaling#streaming)
{{< /hint >}}
Specific to the streaming API, this variable determines how many different processes the streaming API forks into. Defaults to the number of CPU cores minus one.
@ -360,33 +365,45 @@ Defaults to value of `REDIS_NAMESPACE`.
#### `SIDEKIQ_REDIS_URL`
### ElasticSearch {#elasticsearch}
### Elasticsearch {#elasticsearch}
{{< page-ref page="admin/optional/elasticsearch" >}}
{{< page-ref page="admin/elasticsearch" >}}
#### `ES_ENABLED`
If set to `true`, Mastodon will use ElasticSearch for its search functions.
If set to `true`, Mastodon will use Elasticsearch for its search functions.
#### `ES_PRESET`
It controls the ElasticSearch indices configuration (number of shards and replica).
Possible values are:
- `single_node_cluster` (default)
- `small_cluster`
- `large_cluster`
See the [ElasticSearch setup page for details on each setting](../elasticsearch#choosing-the-correct-preset).
#### `ES_HOST`
Host of the ElasticSearch server. Defaults to `localhost`
Host of the Elasticsearch server. Defaults to `localhost`. If using TLS, prepend the hostname with `https://`. For example: `https://elastic.example.com`.
#### `ES_PORT`
Port of the ElasticSearch server. Defaults to `9200`
Port of the Elasticsearch server. Defaults to `9200`
#### `ES_USER`
Used for optionally authenticating with ElasticSearch
Used for optionally authenticating with Elasticsearch
#### `ES_PASS`
Used for optionally authenticating with ElasticSearch
Used for optionally authenticating with Elasticsearch
#### `ES_PREFIX`
Useful if the ElasticSearch server is shared between multiple projects or different Mastodon servers. Defaults to value of `REDIS_NAMESPACE`.
Useful if the Elasticsearch server is shared between multiple projects or different Mastodon servers. Defaults to value of `REDIS_NAMESPACE`.
### StatsD {#statsd}
@ -400,19 +417,34 @@ Example value: `localhost:8125`
If set, all StatsD keys will be prefixed with this. Defaults to `Mastodon.production` when `RAILS_ENV` is `production`, `Mastodon.development` when it's `development`, etc.
#### `STATSD_SIDEKIQ`
If set to `true`, Mastodon will log some Sidekiq metrics into StatsD. Defaults to `false`.
### SMTP email delivery {#smtp}
#### `SMTP_SERVER`
#### `SMTP_PORT`
#### `SMTP_LOGIN`
#### `SMTP_PASSWORD`
#### `SMTP_FROM_ADDRESS`
#### `SMTP_DOMAIN`
#### `SMTP_DELIVERY_METHOD`
#### `SMTP_AUTH_METHOD`
#### `SMTP_CA_FILE`
#### `SMTP_OPENSSL_VERIFY_MODE`
#### `SMTP_ENABLE_STARTTLS_AUTO`
#### `SMTP_ENABLE_STARTTLS`
Set to `auto` (default), `always`, or `never`.
@ -421,11 +453,39 @@ Set to `auto` (default), `always`, or `never`.
4.0.0 - added
#### `SMTP_TLS`
#### `SMTP_SSL`
E-mail configuration is based on the *action_mailer* component of the *Ruby on Rails* framework that Mastodon is built on. Complete documentation on action_mailer is available [here](https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration). The client uses SMTP or derivatives: StartTLS + SMTP or SMTPS (SMTP over TLS).
### Basic configuration {#basic}
* `SMTP_SERVER`: Specify the server to use. For example `sub.domain.tld`.
* `SMTP_PORT`: By default, the value is `25` (usual port for SMTP). If StartTLS is detected, it may be switched to port 587.
* `SMTP_DOMAIN`: Only required if a HELO domain is needed. Will be set to the `SMTP_SERVER` domain by default.
* `SMTP_FROM_ADDRESS`: Specify a sender address.
* `SMTP_DELIVERY_METHOD`: By default, the value is `smtp` (can also be `sendmail`).
### Authentication for the SMTP server {#smtpauthentication}
* `SMTP_LOGIN`: Login for the SMTP user.
* `SMTP_PASSWORD`: Password for the SMTP user.
* `SMTP_AUTH_METHOD`: Either `plain` (default; password is transmitted in the clear), `login` (password will be base64 encoded) or `cram_md5`.
### Secured SMTP
By default, a StartTLS connection will be attempted to the specified SMTP server.
* `SMTP_ENABLE_STARTTLS_AUTO`: Default `true`.
* `SMTP_CA_FILE`: A value may be specified, but on many Linux distros (e.g. Debian-based) this will be `/etc/ssl/certs/ca-certificates.crt`.
* `SMTP_OPENSSL_VERIFY_MODE`: `none` or `peer`. When using TLS, it may be useful to accept connections with a self-signed certificate.
* `SMTP_TLS`: `true` or `false` (default `false`)
* `SMTP_SSL`: `true` or `false` (default `false`)
Note that `TLSv1.3` and `TLSv1.2` are the only SSL/TLS protocols currently considered to be secure.
## File storage {#files}
### CDN {cdn}
### CDN {#cdn}
#### `CDN_HOST`
@ -439,9 +499,9 @@ You must serve the files with CORS headers, otherwise some functions of Mastodon
#### `S3_ALIAS_HOST`
Similar to `CDN_HOST`, you may serve *user-uploaded* files from a separate host. In fact, if you are using external storage like Amazon S3, Minio or Google Cloud, you will by default be serving files from those services' URLs.
Similar to `CDN_HOST`, you may serve _user-uploaded_ files from a separate host. In fact, if you are using external storage like Amazon S3, Minio or Google Cloud, you will by default be serving files from those services' URLs.
It is *extremely recommended* to use your own host instead, for a few reasons:
It is _extremely recommended_ to use your own host instead, for a few reasons:
1. Bandwidth on external storage providers is metered and expensive
2. You may want to switch to a different provider later without breaking old links
@ -457,36 +517,59 @@ You must serve the files with CORS headers, otherwise some functions of Mastodon
### Local file storage {#paperclip}
#### `PAPERCLIP_ROOT_PATH`
#### `PAPERCLIP_ROOT_URL`
### Amazon S3 and compatible {#s3}
#### `S3_ENABLED`
#### `S3_BUCKET`
#### `AWS_ACCESS_KEY_ID`
#### `AWS_SECRET_ACCESS_KEY`
#### `S3_REGION`
#### `S3_PROTOCOL`
#### `S3_HOSTNAME`
#### `S3_ENDPOINT`
#### `S3_SIGNATURE_VERSION`
#### `S3_OVERRIDE_PATH_STYLE`
#### `S3_OPEN_TIMEOUT`
#### `S3_READ_TIMEOUT`
#### `S3_FORCE_SINGLE_REQUEST`
### Swift {#swift}
#### `SWIFT_ENABLED`
#### `SWIFT_USERNAME`
#### `SWIFT_TENANT`
#### `SWIFT_PASSWORD`
#### `SWIFT_PROJECT_ID`
#### `SWIFT_AUTH_URL`
#### `SWIFT_CONTAINER`
#### `SWIFT_OBJECT_URL`
#### `SWIFT_REGION`
#### `SWIFT_DOMAIN_NAME`
#### `SWIFT_CACHE_TTL`
## External authentication {#external-authentication}
@ -495,74 +578,137 @@ You must serve the files with CORS headers, otherwise some functions of Mastodon
#### `OMNIAUTH_ONLY`
#### `ONE_CLICK_SSO_LOGIN`
Enables the `Login or Register` button.
Useful for instances where all authentication takes place using a single
external provider (CAS, SAML or OIDC).
Enabling this will prevent caching for anonymous sessions.
And, when using OIDC discovery, the identity provider has to be available
before Mastodon starts.
### LDAP {#ldap}
#### `LDAP_ENABLED`
#### `LDAP_HOST`
#### `LDAP_PORT`
#### `LDAP_METHOD`
#### `LDAP_BASE`
#### `LDAP_BIND_DN`
#### `LDAP_PASSWORD`
#### `LDAP_UID`
#### `LDAP_SEARCH_FILTER`
#### `LDAP_MAIL`
#### `LDAP_UID_CONVERSTION_ENABLED`
#### `LDAP_UID_CONVERSION_ENABLED`
### PAM {#pam}
#### `PAM_ENABLED`
#### `PAM_EMAIL_DOMAIN`
#### `PAM_DEFAULT_SERVICE`
#### `PAM_CONTROLLED_SERVICE`
### CAS {#cas}
#### `CAS_ENABLED`
#### `CAS_DISPLAY_NAME`
#### `CAS_URL`
#### `CAS_HOST`
#### `CAS_PORT`
#### `CAS_SSL`
#### `CAS_VALIDATE_URL`
#### `CAS_CALLBACK_URL`
#### `CAS_LOGOUT_URL`
#### `CAS_LOGIN_URL`
#### `CAS_UID_FIELD`
#### `CAS_CA_PATH`
#### `CAS_DISABLE_SSL_VERIFICATION`
#### `CAS_UID_KEY`
#### `CAS_NAME_KEY`
#### `CAS_EMAIL_KEY`
#### `CAS_NICKNAME_KEY`
#### `CAS_FIRST_NAME_KEY`
#### `CAS_LAST_NAME_KEY`
#### `CAS_LOCATION_KEY`
#### `CAS_IMAGE_KEY`
#### `CAS_PHONE_KEY`
#### `CAS_SECURITY_ASSUME_EMAIL_IS_VERIFIED`
### SAML {#saml}
#### `SAML_ENABLED`
#### `SAML_ACS_URL`
#### `SAML_ISSUER`
#### `SAML_IDP_SSO_TARGET_URL`
#### `SAML_IDP_CERT`
#### `SAML_IDP_CERT_FINGERPRINT`
#### `SAML_NAME_IDENTIFIER_FORMAT`
#### `SAML_CERT`
#### `SAML_PRIVATE_KEY`
#### `SAML_SECURITY_WANT_ASSERTION_SIGNED`
#### `SAML_SECURITY_WANT_ASSERTION_ENCRYPTED`
#### `SAML_SECURITY_ASSUME_EMAIL_IS_VERIFIED`
#### `SAML_ATTRIBUTES_STATEMENTS_UID`
#### `SAML_ATTRIBUTES_STATEMENTS_EMAIL`
#### `SAML_ATTRIBUTES_STATEMENTS_FULL_NAME`
#### `SAML_ATTRIBUTES_STATEMENTS_FIRST_NAME`
#### `SAML_ATTRIBUTES_STATEMENTS_LAST_NAME`
#### `SAML_UID_ATTRIBUTE`
#### `SAML_ATTRIBUTES_STATEMENTS_VERIFIED`
#### `SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL`
## Hidden services {#hidden-services}
@ -572,7 +718,9 @@ You must serve the files with CORS headers, otherwise some functions of Mastodon
{{< page-ref page="admin/optional/tor" >}}
#### `http_proxy`
#### `http_hidden_proxy`
#### `ALLOW_ACCESS_TO_HIDDEN_SERVICE`
## Limits {#limits}
@ -620,13 +768,21 @@ This variable only has any effect when running `rake db:migrate` and it is extre
### Uncategorized or unsorted
#### `BUNDLE_GEMFILE`
#### `DEEPL_API_KEY`
#### `DEEPL_PLAN`
#### `LIBRE_TRANSLATE_ENDPOINT`
#### `LIBRE_TRANSLATE_API_KEY`
#### `CACHE_BUSTER_ENABLED`
#### `CACHE_BUSTER_SECRET_HEADER`
#### `CACHE_BUSTER_SECRET`
#### `GITHUB_REPOSITORY`
Defaults to `mastodon/mastodon`
@ -636,8 +792,11 @@ Defaults to `mastodon/mastodon`
Defaults to `https://github.com/$GITHUB_REPOSITORY`
#### `FFMPEG_BINARY`
#### `LOCAL_HTTPS`
#### `PATH`
#### `MAX_FOLLOWS_THRESHOLD`
Defaults to `7500`
@ -670,4 +829,5 @@ Defaults to `512`.
#### `GITHUB_API_TOKEN`
Used in a rake task for generating AUTHORS.md from Github commit history.
Used in a rake task for generating AUTHORS.md from GitHub commit history.

View File

@ -0,0 +1,231 @@
---
title: Configuring full-text search
description: Setting up Elasticsearch to search for statuses (authored, favourited, or mentioned), public indexable status, and accounts
aliases:
- /admin/optional/elasticsearch
menu:
docs:
weight: 40
parent: admin
---
Mastodon supports full-text search when Elasticsearch is available. It is strongly recommended to configure this feature.
Mastodons full-text search allows logged in users to find results from:
- public statuses from account that opted into appearing in search results
- their own statuses
- their mentions
- their favourites
- their bookmarks
- accounts (display name, usernames and bios)
It deliberately does not allow searching for arbitrary strings in the entire database.
## Installing Elasticsearch {#install}
{{< hint style="info" >}}
Mastodon is tested with Elasticsearch version 7. It should support OpenSearch, as well as Elasticsearch versions 6 and 8, but those setups are not officially supported.
{{< /hint >}}
Elasticsearch requires a Java runtime. If you dont have Java already installed, do it now. Assuming you are logged in as `root`:
```bash
apt install openjdk-17-jre-headless
```
Add the official Elasticsearch repository to apt:
```bash
wget -O /usr/share/keyrings/elasticsearch.asc https://artifacts.elastic.co/GPG-KEY-elasticsearch
echo "deb [signed-by=/usr/share/keyrings/elasticsearch.asc] https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elastic-7.x.list
```
Now you can install Elasticsearch:
```bash
apt update
apt install elasticsearch
```
{{< hint style="warning" >}}
**Security warning:** By default, Elasticsearch is supposed to bind to localhost only, i.e. be inaccessible from the outside network. You can check which address Elasticsearch binds to by looking at `network.host` within `/etc/elasticsearch/elasticsearch.yml`. Consider that anyone who can access Elasticsearch can access and modify any data within it, as there is no authentication layer. So its really important that the access is secured. Having a firewall that only exposes the 22, 80 and 443 ports is advisable, as outlined in the [main installation instructions](../../prerequisites/#install-a-firewall-and-only-whitelist-ssh-http-and-https-ports). If you have a multi-host setup, you must know how to secure internal traffic.
{{< /hint >}}
To start Elasticsearch:
```bash
systemctl daemon-reload
systemctl enable --now elasticsearch
```
## Configuring Mastodon {#config}
Edit `.env.production` to add the following variables:
```bash
ES_ENABLED=true
ES_HOST=localhost
ES_PORT=9200
ES_PRESET= # single_node_cluster, small_cluster or large_cluster
# ES_USER=
# ES_PASS=
```
_Note_: If using TLS, prepend the hostname with `https://`. For example: `https://elastic.example.com`.
### Choosing the correct preset
The value for `ES_PRESET` depends on the size of your Elasticsearch and will be used to set the number of shards and replica for your indices to the best value for your setup:
- `single_node_cluster` if you only have one node in your Elasticsearch cluster. Indices will be configured without any replica
- `small_cluster` if you have less than 6 nodes in your cluster. Indices will be configured with 1 replica
- `large_cluster` if you have 6 or more nodes in your cluster. Indices will be configured with more shards than with the `small_cluster` setting, to allow them to be distributed over more nodes
If you have multiple Mastodon servers on the same machine, and you are planning to use the same Elasticsearch installation for all of them, make sure that all of them have unique `REDIS_NAMESPACE` in their configurations, to differentiate the indices. If you need to override the prefix of the Elasticsearch indices, you can set `ES_PREFIX` directly.
### Security
By default, Elasticsearch does not handle any authentication and every request is made with full admin permission. We strongly advise you to configure Elasticsearch security features on your cluster.
To configure it, please refer [to the official documentation](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-minimal-setup.html). It will guide you through:
- Enabling the security features (`xpack.security.enabled: true`)
- Creating password for built-in users
Once done, you can create a custom role for Mastodon to connect.
For example (please adapt this snippet to use your Elastic admin password):
```sh
curl -X POST -u elastic:admin_password "localhost:9200/_security/role/mastodon_full_access?pretty" -H 'Content-Type: application/json' -d'
{
"cluster": ["monitor"],
"indices": [{
"names": ["*"],
"privileges": ["read", "monitor", "write", "manage"]
}]
}
'
```
[Elasticsearch documentation for role creation](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-api-put-role.html)
Once the role is created, you can create a user for the Mastodon server to use, and assign it the role.
For example (please adapt this snippet to use your Elastic admin password, and customize your new user `mastodon` user password):
```sh
curl -X POST -u elastic:admin_password "localhost:9200/_security/user/mastodon?pretty" -H 'Content-Type: application/json' -d'
{
"password" : "l0ng-r4nd0m-p@ssw0rd",
"roles" : ["mastodon_full_access"]
}
'
```
[Elasticsearch documentation for user creation](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/security-api-put-user.html)
Once this is done, you need to configure Mastodon to use the credentials for your newly created user.
In `.env.production`, adjust your configuration:
```bash
ES_USER=mastodon
ES_PASS=l0ng-r4nd0m-p@ssw0rd
```
You are all set, and your Elasticsearch server should be much more secure!
### Populate the indices
After saving the new configuration, restart Mastodon processes for it to take effect:
```bash
systemctl restart mastodon-sidekiq
systemctl reload mastodon-web
```
Now it's time to create the Elasticsearch indices and fill them with data:
```bash
su - mastodon
cd live
RAILS_ENV=production bin/tootctl search deploy
```
## Search optimization for other languages
### Chinese search optimization {#chinese-search-optimization}
The default analyzer of the Elasticsearch is the standard analyzer, which may not be the best especially for Chinese. To improve search experience, you can install a language specific analyzer. Before creating the indices in Elasticsearch, install the following Elasticsearch extensions:
- [elasticsearch-analysis-ik](https://github.com/medcl/elasticsearch-analysis-ik)
- [elasticsearch-analysis-stconvert](https://github.com/medcl/elasticsearch-analysis-stconvert)
And then modify Mastodon's index definition as follows:
```diff
diff --git a/app/chewy/accounts_index.rb b/app/chewy/accounts_index.rb
--- a/app/chewy/accounts_index.rb
+++ b/app/chewy/accounts_index.rb
@@ -4,7 +4,7 @@ class AccountsIndex < Chewy::Index
settings index: { refresh_interval: '5m' }, analysis: {
analyzer: {
content: {
- tokenizer: 'whitespace',
+ tokenizer: 'ik_max_word',
filter: %w(lowercase asciifolding cjk_width),
},
diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb
--- a/app/chewy/statuses_index.rb
+++ b/app/chewy/statuses_index.rb
@@ -16,9 +16,17 @@ class StatusesIndex < Chewy::Index
language: 'possessive_english',
},
},
+ char_filter: {
+ tsconvert: {
+ type: 'stconvert',
+ keep_both: false,
+ delimiter: '#',
+ convert_type: 't2s',
+ },
+ },
analyzer: {
content: {
- tokenizer: 'uax_url_email',
+ tokenizer: 'ik_max_word',
filter: %w(
english_possessive_stemmer
lowercase
@@ -27,6 +35,7 @@ class StatusesIndex < Chewy::Index
english_stop
english_stemmer
),
+ char_filter: %w(tsconvert),
},
},
}
diff --git a/app/chewy/tags_index.rb b/app/chewy/tags_index.rb
--- a/app/chewy/tags_index.rb
+++ b/app/chewy/tags_index.rb
@@ -2,10 +2,19 @@
class TagsIndex < Chewy::Index
settings index: { refresh_interval: '15m' }, analysis: {
+ char_filter: {
+ tsconvert: {
+ type: 'stconvert',
+ keep_both: false,
+ delimiter: '#',
+ convert_type: 't2s',
+ },
+ },
analyzer: {
content: {
- tokenizer: 'keyword',
+ tokenizer: 'ik_max_word',
filter: %w(lowercase asciifolding cjk_width),
+ char_filter: %w(tsconvert),
},
edge_ngram: {
```

View File

@ -74,7 +74,6 @@ And proceed to install rbenv and rbenv-build:
```bash
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec bash
@ -84,8 +83,8 @@ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
Once this is done, we can install the correct Ruby version:
```bash
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.0.4
rbenv global 3.0.4
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.2.2
rbenv global 3.2.2
```
Well also need to install bundler:
@ -106,7 +105,7 @@ exit
#### Performance configuration (optional) {#performance-configuration-optional}
For optimal performance, you may use [pgTune](https://pgtune.leopard.in.ua/#/) to generate an appropriate configuration and edit values in `/etc/postgresql/15/main/postgresql.conf` before restarting PostgreSQL with `systemctl restart postgresql`
For optimal performance, you may use [pgTune](https://pgtune.leopard.in.ua/#/) to generate an appropriate configuration and edit values in `/etc/postgresql/16/main/postgresql.conf` before restarting PostgreSQL with `systemctl restart postgresql`
#### Creating a user {#creating-a-user}
@ -141,7 +140,7 @@ Use git to download the latest stable release of Mastodon:
```bash
git clone https://github.com/mastodon/mastodon.git live && cd live
git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)
git checkout $(git tag -l | grep '^v[0-9.]*$' | sort -V | tail -n 1)
```
#### Installing the last dependencies {#installing-the-last-dependencies}
@ -181,6 +180,16 @@ Youre done with the mastodon user for now, so switch back to root:
exit
```
### Acquiring a SSL certificate {#acquiring-a-ssl-certificate}
Well use Lets Encrypt to get a free SSL certificate:
```bash
certbot certonly --nginx -d example.com
```
This will obtain the certificate, and save it in the directory `/etc/letsencrypt/live/example.com/`.
### Setting up nginx {#setting-up-nginx}
Copy the configuration template for nginx from the Mastodon directory:
@ -192,23 +201,14 @@ ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon
Then edit `/etc/nginx/sites-available/mastodon` to replace `example.com` with your own domain name, and make any other adjustments you might need.
Reload nginx for the changes to take effect:
Un-comment the lines starting with `ssl_certificate` and `ssl_certificate_key`, updating the path with the correct domain name.
Reload nginx for the changes to take effect:
```bash
systemctl reload nginx
```
### Acquiring a SSL certificate {#acquiring-a-ssl-certificate}
Well use Lets Encrypt to get a free SSL certificate:
```bash
certbot --nginx -d example.com
```
This will obtain the certificate, automatically update `/etc/nginx/sites-available/mastodon` to use the new certificate, and reload nginx for the changes to take effect.
At this point you should be able to visit your domain in the browser and see the elephant hitting the computer screen error page. This is because we havent started the Mastodon process yet.
### Setting up systemd services {#setting-up-systemd-services}

View File

@ -41,6 +41,8 @@ If the account is reinstated within the 30 day period, all data is once again ac
Once the data has been deleted, whether that is after the 30 day period, or if an admin has force deleted it, the account can still be un-suspended. However, the account will have no data (statuses, profile information, avatar or header image) associated with it.
For remote accounts, suspending will make them unfollow any local account. Those relationships are not restored in case the remote account is un-suspended, even within the 30-day time window.
## Moderating entire websites {#server-wide-moderation}
Because individually moderating a large volume of users from a misbehaving server can be exhausting, it is possible to pre-emptively moderate against all users from that particular server using a so-called **domain block**, which comes with several different levels of severity.
@ -57,6 +59,8 @@ Equivalent to [limiting](#limit-user) all past and future accounts from the serv
Equivalent to [suspending](#suspend-user) all past and future accounts from the server. No content from the server will be stored locally except for usernames.
Suspending a server will remove all existing follow relationships between local accounts and accounts on the suspended server. They will not be restored in case the remote server is un-suspended later.
## Spam-fighting measures {#spam-fighting-measures}
There are a few baseline measures for preventing spam in Mastodon:
@ -86,3 +90,229 @@ sudo iptables -I INPUT 1 -m set --match-set spambots src -j DROP
```
Be careful not to lock yourself out of your machine.
### Webhooks for moderation-level events {#report-events-webhook}
Webhooks can be created to facilitate automation through the moderation API by notifying applications about system events in real-time. This also enables integrations with chat apps like Discord, IRC and Slack, helping moderator coordination.
The X-Hub-Signature header adopted from the WebSub spec can be optionally used to verify that the payloads are authentic.
Events currently supported:
* account.approved
* account.created
* account.updated
* report.created
* report.updated
* status.created
* status.updated
#### Example payload:
```json
{
"event":"report.created",
"created_at":"2023-10-26T13:34:00.351Z",
"object":{
"id":"8437",
"action_taken":false,
"action_taken_at":null,
"category":"violation",
"comment":"",
"forwarded":true,
"created_at":"2023-10-26T13:34:00.348Z",
"updated_at":"2023-10-26T13:34:00.348Z",
"account":{
"id":"123456789",
"username":"bobisaburger",
"domain":null,
"created_at":"2023-07-13T04:39:22.493Z",
"email":"bobisaburger@emailservice.com",
"ip":"12.34.56.78",
"confirmed":true,
"suspended":false,
"silenced":false,
"sensitized":false,
"disabled":false,
"approved":true,
"locale":"en",
"invite_request":"I would love to be a member of your instance!",
"ips":[
{
"ip":"12.34.56.78",
"used_at":"2023-07-13T04:45:31.835Z"
},
{
"ip":"98.76.54.32",
"used_at":"2023-07-13T04:39:22.722Z"
}
],
"account":{
"id":"123456789",
"username":"bobisaburger",
"acct":"bobisaburger",
"display_name":"bobisaburger",
"locked":false,
"bot":false,
"discoverable":null,
"group":false,
"created_at":"2023-07-13T00:00:00.000Z",
"note":"",
"url":"https://mastodonwebsite/@bobisaburger",
"uri":"https://mastodonwebsite/users/bobisaburger",
"avatar":"https://locationofavatar.com/image.jpg",
"avatar_static":"https://locationofavatar.com/image.jpg",
"header":"locationofheader.com/image.jpg",
"header_static":"locationofheader.com/image.jpg",
"followers_count":100,
"following_count":200,
"statuses_count":9,
"last_status_at":"2023-08-05",
"noindex":true,
"emojis":[
],
"roles":[
],
"fields":[
]
},
"role":{
"id":"-99",
"name":"",
"permissions":"65536",
"color":"",
"highlighted":false
}
},
"target_account":{
"id":"123454321",
"username":"cheeseperson",
"domain":"someothermastodonsite.com",
"created_at":"2023-08-20T00:00:00.000Z",
"email":null,
"ip":null,
"confirmed":null,
"suspended":false,
"silenced":false,
"sensitized":false,
"disabled":null,
"approved":null,
"locale":null,
"invite_request":null,
"ips":null,
"account":{
"id":"123454321",
"username":"cheeseperson",
"acct":"cheeseperson@someothermastodonsite.com",
"display_name":"cheeseperson",
"locked":false,
"bot":false,
"discoverable":false,
"group":false,
"created_at":"2023-08-20T00:00:00.000Z",
"note":"",
"url":"https://someothermastodonsite.com/@cheeseperson",
"uri":"https://someothermastodonsite.com/users/cheeseperson",
"avatar":"https://someothermastadonsite.com/avatars/original/missing.png",
"avatar_static":"https://someothermastadonsite.com/avatars/original/missing.png",
"header":"locationofheader.com/image.jpg",
"header_static":"locationofheader.com/image.jpg",
"followers_count":2,
"following_count":2,
"statuses_count":95,
"last_status_at":"2023-10-26",
"emojis":[
],
"fields":[
]
},
"role":null
},
"assigned_account":null,
"action_taken_by_account":null,
"statuses":[
{
"id":"12345678987654321",
"created_at":"2023-10-26T11:29:13.000Z",
"in_reply_to_id":"1918282746465",
"in_reply_to_account_id":"101010101010",
"sensitive":false,
"spoiler_text":"",
"visibility":"public",
"language":"de",
"uri":"https://someothermastodonsite.com/users/cheeseperson/statuses/111301083360371621",
"url":"https://someothermastodonsite.com/@cheeseperson/111301083360371621",
"replies_count":0,
"reblogs_count":0,
"favourites_count":0,
"edited_at":"2023-10-26T11:30:31.000Z",
"content":"<p>Here is some content</p>",
"reblog":null,
"account":{
"id":"123454321",
"username":"cheeseperson",
"acct":"cheeseperson@someothermastodonsite.com",
"display_name":"cheeseperson",
"locked":false,
"bot":false,
"discoverable":false,
"group":false,
"created_at":"2023-08-20T00:00:00.000Z",
"note":"",
"url":"https://someothermastodonsite.com/@cheeseperson",
"uri":"https://someothermastodonsite.com/users/cheeseperson",
"avatar":"https://someothermastadonsite.com/avatars/original/missing.png",
"avatar_static":"https://someothermastadonsite.com/avatars/original/missing.png",
"header":"locationofheader.com/image.jpg",
"header_static":"locationofheader.com/image.jpg",
"followers_count":2,
"following_count":2,
"statuses_count":95,
"last_status_at":"2023-10-26",
"emojis":[
],
"fields":[
]
},
"media_attachments":[
],
"mentions":[
{
"id":"101010101010",
"username":"thirdperson",
"url":"https://thirdpersonsinstance.com/@thirdperson",
"acct":"thirdperson@emailwebsite.com"
}
],
"tags":[
],
"emojis":[
],
"card":null,
"poll":null
}
],
"rules":[
{
"id":"2",
"text":"Don't be a meanie!"
}
]
}
}
```

View File

@ -9,6 +9,6 @@ menu:
Mastodon offers a few optional features that can be used if needed.
- [Full-text search](./elasticsearch/)
- [Object storage](./object-storage/)
- [Hidden services](./tor/)
- [Single Sign On](./sso/)

View File

@ -1,154 +0,0 @@
---
title: Full-text search
description: Setting up ElasticSearch to search for statuses authored, favourited, or mentioned in.
menu:
docs:
weight: 10
parent: admin-optional
---
Mastodon supports full-text search when ElasticSearch is available. Mastodons full-text search allows logged in users to find results from their own statuses, their mentions, their favourites, and their bookmarks. It deliberately does not allow searching for arbitrary strings in the entire database.
## Installing ElasticSearch {#install}
ElasticSearch requires a Java runtime. If you dont have Java already installed, do it now. Assuming you are logged in as `root`:
```bash
apt install openjdk-17-jre-headless
```
Add the official ElasticSearch repository to apt:
```bash
wget -O /usr/share/keyrings/elasticsearch.asc https://artifacts.elastic.co/GPG-KEY-elasticsearch
echo "deb [signed-by=/usr/share/keyrings/elasticsearch.asc] https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elastic-7.x.list
```
Now you can install ElasticSearch:
```bash
apt update
apt install elasticsearch
```
{{< hint style="warning" >}}
**Security warning:** By default, ElasticSearch is supposed to bind to localhost only, i.e. be inaccessible from the outside network. You can check which address ElasticSearch binds to by looking at `network.host` within `/etc/elasticsearch/elasticsearch.yml`. Consider that anyone who can access ElasticSearch can access and modify any data within it, as there is no authentication layer. So its really important that the access is secured. Having a firewall that only exposes the 22, 80 and 443 ports is advisable, as outlined in the [main installation instructions](../../prerequisites/#install-a-firewall-and-only-whitelist-ssh-http-and-https-ports). If you have a multi-host setup, you must know how to secure internal traffic.
{{< /hint >}}
{{< hint style="danger" >}}
**Security warning:** ElasticSearch versions between `2.0` and `2.14.1` are affected by an [exploit](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228) in the `log4j` library. If affected, please refer to the [temporary mitigation](https://github.com/elastic/elasticsearch/issues/81618#issuecomment-991000240) from the ElasticSearch issue tracker.
{{< /hint >}}
To start ElasticSearch:
```bash
systemctl daemon-reload
systemctl enable --now elasticsearch
```
## Configuring Mastodon {#config}
Edit `.env.production` to add the following variables:
```bash
ES_ENABLED=true
ES_HOST=localhost
ES_PORT=9200
```
If you have multiple Mastodon servers on the same machine, and you are planning to use the same ElasticSearch installation for all of them, make sure that all of them have unique `REDIS_NAMESPACE` in their configurations, to differentiate the indices. If you need to override the prefix of the ElasticSearch indices, you can set `ES_PREFIX` directly.
After saving the new configuration, restart Mastodon processes for it to take effect:
```bash
systemctl restart mastodon-sidekiq
systemctl reload mastodon-web
```
Now it's time to create the ElasticSearch indices and fill them with data:
```bash
su - mastodon
cd live
RAILS_ENV=production bin/tootctl search deploy
```
## Search optimization for other languages
### Chinese search optimization {#chinese-search-optimization}
The default analyzer of the ElasticSearch is the standard analyzer, which may not be the best especially for Chinese. To improve search experience, you can install a language specific analyzer. Before creating the indices in ElasticSearch, install the following ElasticSearch extensions:
- [elasticsearch-analysis-ik](https://github.com/medcl/elasticsearch-analysis-ik)
- [elasticsearch-analysis-stconvert](https://github.com/medcl/elasticsearch-analysis-stconvert)
And then modify Mastodon's index definition as follows:
```diff
diff --git a/app/chewy/accounts_index.rb b/app/chewy/accounts_index.rb
--- a/app/chewy/accounts_index.rb
+++ b/app/chewy/accounts_index.rb
@@ -4,7 +4,7 @@ class AccountsIndex < Chewy::Index
settings index: { refresh_interval: '5m' }, analysis: {
analyzer: {
content: {
- tokenizer: 'whitespace',
+ tokenizer: 'ik_max_word',
filter: %w(lowercase asciifolding cjk_width),
},
diff --git a/app/chewy/statuses_index.rb b/app/chewy/statuses_index.rb
--- a/app/chewy/statuses_index.rb
+++ b/app/chewy/statuses_index.rb
@@ -16,9 +16,17 @@ class StatusesIndex < Chewy::Index
language: 'possessive_english',
},
},
+ char_filter: {
+ tsconvert: {
+ type: 'stconvert',
+ keep_both: false,
+ delimiter: '#',
+ convert_type: 't2s',
+ },
+ },
analyzer: {
content: {
- tokenizer: 'uax_url_email',
+ tokenizer: 'ik_max_word',
filter: %w(
english_possessive_stemmer
lowercase
@@ -27,6 +35,7 @@ class StatusesIndex < Chewy::Index
english_stop
english_stemmer
),
+ char_filter: %w(tsconvert),
},
},
}
diff --git a/app/chewy/tags_index.rb b/app/chewy/tags_index.rb
--- a/app/chewy/tags_index.rb
+++ b/app/chewy/tags_index.rb
@@ -2,10 +2,19 @@
class TagsIndex < Chewy::Index
settings index: { refresh_interval: '15m' }, analysis: {
+ char_filter: {
+ tsconvert: {
+ type: 'stconvert',
+ keep_both: false,
+ delimiter: '#',
+ convert_type: 't2s',
+ },
+ },
analyzer: {
content: {
- tokenizer: 'keyword',
+ tokenizer: 'ik_max_word',
filter: %w(lowercase asciifolding cjk_width),
+ char_filter: %w(tsconvert),
},
edge_ngram: {
```

View File

@ -37,7 +37,7 @@ server {
}
resolver 8.8.8.8;
proxy_set_header Host YOUR_S3_HOSTNAME;
proxy_set_header Host YOUR_BUCKET_NAME.YOUR_S3_HOSTNAME;
proxy_set_header Connection '';
proxy_set_header Authorization '';
proxy_hide_header Set-Cookie;
@ -63,6 +63,8 @@ server {
add_header Cache-Control public;
add_header 'Access-Control-Allow-Origin' '*';
add_header X-Cache-Status $upstream_cache_status;
add_header X-Content-Type-Options nosniff;
add_header Content-Security-Policy "default-src 'none'; form-action 'none'";
}
}
```

View File

@ -0,0 +1,232 @@
---
title: Configuring object storage
description: Serving user-uploaded files in Mastodon using external object storage
menu:
docs:
weight: 15
parent: admin-optional
---
User-uploaded files can be stored on the main server's file system, or using an external object storage server, which can be required for scaling.
## Using the filesystem {#FS}
The simplest way to store user uploads is by using the server's file system. This is how it works by default and is suitable for small servers.
By default, Mastodon will store file uploads under `public/system` in its installation directory, but that can be overridden using the `PAPERCLIP_ROOT_PATH` environment variable.
By default, the files are served at `https://your-domain/system`, which can be overridden using `PAPERCLIP_ROOT_URL` and `CDN_HOST`.
{{< hint style="info" >}}
While using the server's file system is perfectly serviceable for small servers, using external object storage is more scalable.
{{</ hint >}}
{{< hint style="danger" >}}
The web server must be configured to serve those files but not allow listing them (that is, `https://your-domain/system/` should not return a file list). This should be the case if you use the configuration files distributed with Mastodon, but it is worth double-checking.
{{</ hint >}}
## S3-compatible object storage backends {#S3}
Mastodon can use S3-compatible object storage backends. ACL support is recommended as it allows Mastodon to quickly make the content of temporarily suspended users unavailable, or marginally improve security of private data.
On Mastodon's end, you need to configure the following environment variables:
- `S3_ENABLED=true`
- `S3_BUCKET=mastodata` (replacing `mastodata` with the name of your bucket)
- `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` need to be set to your credentials
- `S3_ALIAS_HOST` is optional but highly recommended in order to set up a caching proxy and not lock you to a specific provider
- `S3_REGION`
- `S3_HOSTNAME` (optional if you use Amazon AWS)
- `S3_PERMISSION` (optional, if you use a provider that does not support ACLs or want to use custom ACLs)
- `S3_FORCE_SINGLE_REQUEST=true` (optional, if you run in trouble processing large files)
{{< page-ref page="admin/optional/object-storage-proxy.md" >}}
{{< hint style="info" >}}
You must serve the files with CORS headers, otherwise some functions of Mastodon's web UI will not work. For example, `Access-Control-Allow-Origin: *`
{{</ hint >}}
{{< hint style="danger" >}}
In any case, your S3 bucket must be configured so that -- ACL configuration nonwithstanding -- all objects are publicly readable but neither writable or listable, while Mastodon itself can write to it. The configuration should be similar for all S3 providers, but common ones have been highlighted below.
{{</ hint >}}
### MinIO
MinIO is an open source implementation of an S3 object provider. This section does not cover how to install it, but how to configure a bucket for use in Mastodon.
You need to set a policy for anonymous access that allows read-only access to objects contained by the bucket without allowing listing them.
To do this, you need to set a custom policy (replace `mastodata` by the actual name of your S3 bucket):
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mastodata/*"
}
]
}
```
Mastodon itself needs to be able to write to the bucket, so either use your admin MinIO account (discouraged) or an account specific to Mastodon (recommended) with the following policy attached (replace `mastodata` by the actual name of your S3 bucket):
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::mastodata/*"
}
]
}
```
You can set those policies from the MinIO Console (web-based user interface) or the command-line client (`mcli` / `mc`).
#### Using the MinIO Console
Connect to the MinIO Console web interface and create a new bucket (or navigate to your existing bucket):
![](/assets/object-storage/minio-bucket.png)
Then, configure the “Access Policy” to a custom one that allows read access (`s3:GetObject`) without write access or ability to list objects (see above):
![](/assets/object-storage/minio-access-policy.png)
{{< hint style="info" >}}
If the MinIO Console does not allow you to set a “Custom” policy, you will likely need to update MinIO. If you are using MinIO in *standalone* or *filesystem* mode, [`RELEASE.2022-10-24T18-35-07Z`](https://github.com/minio/minio/releases/tag/RELEASE.2022-10-24T18-35-07Z) should be a safe version to update to that does not require [an involved migration procedure](https://min.io/docs/minio/linux/operations/install-deploy-manage/migrate-fs-gateway.html#migrate-from-gateway-or-filesystem-mode).
{{< /hint >}}
Create a new `mastodon-readwrite` policy (see above):
![](/assets/object-storage/minio-mastodon-readwrite.png)
Finally, create a new `mastodon` user with the `mastodon-readwrite` policy:
![](/assets/object-storage/minio-mastodon-user.png)
#### Using the command-line utility
The same can be achieved using the [MinIO Client](https://min.io/docs/minio/linux/reference/minio-mc.html) command-line utility (can be called `mc` or `mcli` depending on where it is installed from).
Create a new bucket:
`mc mb myminio/mastodata`
Save the anonymous access policy from above as `anonymous-readonly-policy.json` and the Mastodon user access policy as `mastodon-readwrite.json` (make sure to replace `mastodata` with the name of your newly-created bucket).
Set the anonymous access policy for your bucket:
`mc anonymous set-json anonymous-readonly-policy.json myminio/mastodata`
Add a `mastodon-readwrite` policy:
`mc admin policy add myminio mastodon-readwrite mastodon-readwrite.json`
Add the `mastodon` user (replace the password):
`mc admin user add myminio mastodon SECRET_PASSWORD`
Apply the `mastodon-readwrite` policy to the `mastodon` user:
`mc admin policy set myminio mastodon-readwrite user=mastodon`
### Wasabi Object Storage
Create a new bucket and define its policy to allow objects to be anonymously readable but not listable:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mastodata/*"
}
]
}
```
![](/assets/object-storage/wasabi-access-policy.png)
{{< hint style="info" >}}
If you are using an old bucket, ensure you are not giving “Everyone” read access to objects through Wasabi's legacy Access Control settings, as that allows listing objects and take precedence over the IAM policy defined above.
![](/assets/object-storage/wasabi-access-control.png)
{{< /hint >}}
Then, create a `mastodon-readwrite` policy to grant read and write access to your bucket:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::mastodata/*"
}
]
}
```
![](/assets/object-storage/wasabi-mastodon-readwrite.png)
Finally, create a new `mastodon` user and don't forget to enable the `mastodon-readwrite` policy:
![](/assets/object-storage/wasabi-mastodon-user.png)
On Mastodon's side, you need to set `S3_FORCE_SINGLE_REQUEST=true` to properly handle large uploads.
### DigitalOcean Spaces
In your DigitalOcean Spaces Bucket, make sure that “File Listing” is “Restricted” to users with access keys.
![](/assets/object-storage/do-spaces.png)
### Scaleway
If you want to use Scaleway Object Storage, we strongly recommend you to create a Scaleway project dedicaced to your Mastodon instance assets and to use a custom IAM policy.
First, create a new Scaleway project, in which you create your object storage bucket. You need to set your bucket visibility to "Private" to not allow objects to be listed.
![](/assets/object-storage/scaleway-bucket.png)
Now that your bucket is created, you need to create API keys to be used in your Mastodon instance configuration.
Head to the IAM settings (in your organisation menu, top right of the screen), and create a new IAM policy (eg `mastodon-media-access`)
![](/assets/object-storage/scaleway-policy.jpg)
This policy needs to have one rule, allowing it to read, write and delete objects in the Scaleway project you created above (the scope).
![](/assets/object-storage/scaleway-policy-rules.jpg)
Then head to the IAM Applications page, and a create a new one (eg `my-mastodon-instance`) and select the policy you created above.
Finally, click on the application you just created, then "API Keys", and create a new API key to use in your instance configuration. You should use the "Yes, set up preferred Project" option and select the project you created above as the default project for this key.
![](/assets/object-storage/scaleway-api-key.png)
Copy the Access Key ID and Secret, and use them for your `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` Mastodon config variables.
### Exoscale
In Exoscale, your bucket should not have any read ACLs (Mastodon will set the ACLs on the object themselves as appropriate).
You need to create an API Key for the Mastodon app, restricted to the Object Storage (`sos`) service, restricted to your bucket, and with unrestricted operations.
![](/assets/object-storage/exoscale.png)
On Mastodon's side, you need to set `S3_FORCE_SINGLE_REQUEST=true` to properly handle large uploads.
### Cloudflare R2
Cloudflare R2 does not support ACLs, so Mastodon needs to be instructed not to try setting them. To do that, set the `S3_PERMISSION` environment variable to an empty string.
{{< hint style="warning" >}}
Without support for ACLs, media files from temporarily-suspended users will remain accessible.
{{< /hint >}}
To get credentials for use in Mastodon, selecte “Manage R2 API Tokens” and create a new API token with “Edit” permissions.
{{< hint style="warning" >}}
This section is currently under construction.
{{< /hint >}}

View File

@ -1,6 +1,6 @@
---
title: Hidden services
description: Serving Mastodon through TOR hidden services.
title: Onion services
description: Serving Mastodon through Tor onion services.
menu:
docs:
weight: 20
@ -36,7 +36,7 @@ apt install tor deb.torproject.org-keyring
Edit the file at `/etc/tor/torrc` and add the following configuration.
```text
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServiceDir /var/lib/tor/onion_service/
HiddenServiceVersion 3
HiddenServicePort 80 127.0.0.1:80
```
@ -47,7 +47,7 @@ Restart tor.
sudo service tor restart
```
Your tor hostname can now be found at `/var/lib/tor/hidden_service/hostname`.
Your tor hostname can now be found at `/var/lib/tor/onion_service/hostname`.
## Move your Mastodon configuration {#nginx}
@ -134,7 +134,7 @@ server {
}
```
Replace the long hash provided here with your Tor domain located in the file at `/var/lib/tor/hidden_service/hostname`.
Replace the long hash provided here with your Tor domain located in the file at `/var/lib/tor/onion_service/hostname`.
Note that the onion hostname has been prefixed with “mastodon.”. Your Tor address acts a wildcard domain. All subdomains will be routed through, and you can configure Nginx to respond to any subdomain you wish. If you do not wish to host any other services on your tor address you can omit the subdomain, or choose a different subdomain.

View File

@ -11,16 +11,16 @@ menu:
Mastodon has three types of processes:
* Web (Puma)
* Streaming API
* Background processing (Sidekiq)
- Web (Puma)
- Streaming API
- Background processing (Sidekiq)
### Web (Puma) {#web}
The web process serves short-lived HTTP requests for most of the application. The following environment variables control it:
* `WEB_CONCURRENCY` controls the number of worker processes
* `MAX_THREADS` controls the number of threads per process
- `WEB_CONCURRENCY` controls the number of worker processes
- `MAX_THREADS` controls the number of threads per process
Threads share the memory of their parent process. Different processes allocate their own memory, though they share some memory via copy-on-write. A larger number of threads maxes out your CPU first, a larger number of processes maxes out your RAM first.
@ -32,10 +32,53 @@ In terms of throughput, more processes are better than more threads.
The streaming API handles long-lived HTTP and WebSockets connections, through which clients receive real-time updates. The following environment variables control it:
* `STREAMING_CLUSTER_NUM` controls the number of worker processes
* `STREAMING_API_BASE_URL` controls the base URL of the streaming API
- `STREAMING_API_BASE_URL` controls the base URL of the streaming API
- `PORT` controls the port the streaming server will listen on, by default 4000. The `BIND` and `SOCKET` environment variables are also able to be used.
- Additionally the shared [database](/admin/config#postgresql) and [redis](/admin/config#redis) environment variables are used.
One process can handle a reasonably high number of connections. The streaming API can be hosted on a different subdomain if you want to e.g. avoid the overhead of nginx proxying the connections.
The streaming API can be use a different subdomain if you want to by setting `STREAMING_API_BASE_URL`, this allows you to have one load balancer for streaming and one for web/API requests. However, this also requires applications to correctly request the streaming URL from the [instance endpoint](/methods/instance/#v2), instead of assuming that it's hosted on the same host as the Web API.
One process of the streaming server can handle a reasonably high number of connections and throughput, but if you find that a single process isn't handling your instance's load, you can run multiple processes by varying the `PORT` number of each, and then using nginx to load balance traffic to each of those instances. For example, a community of about 50,000 accounts with 10,000-20,000 monthly active accounts, you'll typically have an average concurrent load of about 800-1200 streaming connections.
The streaming server also exposes a [Prometheus](https://prometheus.io/) endpoint on `/metrics` with a lot of metrics to help you understand the current load on your mastodon streaming server, some key metrics are:
* `mastodon_streaming_connected_clients`: This is the number of connected clients, tagged by client type (websocket or eventsource)
* `mastodon_streaming_connected_channels`: This is the number of "channels" that are currently subscribed (note that this is much higher than connected clients due to how our internal "system" channels currently work)
* `mastodon_streaming_messages_sent_total`: This is the total number of messages sent to clients since last restart.
* `mastodon_streaming_redis_messages_received_total`: This is the number of messages received from Redis pubsub, and intended to complement [monitoring Redis directly](https://sysdig.com/blog/redis-prometheus/).
{{< hint style="info" >}}
The more streaming server processes that you run, the more database connections will be consumed on PostgreSQL, so you'll likely want to use PgBouncer, as documented below.
{{< /hint >}}
An example nginx configuration to route traffic to three different processes on `PORT` 4000, 4001, and 4002 is as follows:
```
upstream streaming {
least_conn;
server 127.0.0.1:4000 fail_timeout=0;
server 127.0.0.1:4001 fail_timeout=0;
server 127.0.0.1:4002 fail_timeout=0;
}
```
If you're using the distributed systemd files, then you can start up multiple streaming servers with the following commands:
```
$ sudo systemctl start mastodon-streaming@4000.service
$ sudo systemctl start mastodon-streaming@4001.service
$ sudo systemctl start mastodon-streaming@4002.service
```
By default, `sudo systemctl start mastodon-streaming` starts just one process on port 4000, equivalent to running `sudo systemctl start mastodon-streaming@4000.service`.
{{< hint style="warning" >}}
Previous versions of Mastodon had a `STREAMING_CLUSTER_NUM` environment variable that made the streaming server use clustering, which started mulitple workers processes and used node.js to load balance them.
This interacted with the other settings in ways which made capacity planning difficult, especially when it comes to database connections and CPU resources. By default the streaming server would consume resources on all available CPUs which could cause contention with other software running on that server. Another common issue was that misconfiguring the `STREAMING_CLUSTER_NUM` would exhaust your database connections by opening up a connection pool per cluster worker process, so a `STREAMING_CLUSTER_NUM` of `5` and `DB_POOL` of `10` would potentially consume 50 database connections.
Now a single streaming server process will only use at maximum `DB_POOL` PostgreSQL connections, and scaling is handled by running more instances of the streaming server.
{{< /hint >}}
### Background processing (Sidekiq) {#sidekiq}
@ -57,14 +100,14 @@ Would start the sidekiq process with 15 threads. Please mind that each threads n
Sidekiq uses different queues for tasks of varying importance, where importance is defined by how much it would impact the user experience of your servers local users if the queue wasnt working, in order of descending importance:
| Queue | Significance |
| :--- | :--- |
| `default` | All tasks that affect local users |
| `push` | Delivery of payloads to other servers |
| `mailers` | Delivery of e-mails |
| `pull` | Lower priority tasks such as handling imports, backups, resolving threads, deleting users, forwarding replies |
| `scheduler` | Doing cron jobs like refreshing trending hashtags and cleaning up logs |
| `ingress` | Incoming remote activities. Lower priority than the default queue so local users still see their posts when the server is under load |
| Queue | Significance |
| :---------- | :----------------------------------------------------------------------------------------------------------------------------------- |
| `default` | All tasks that affect local users |
| `push` | Delivery of payloads to other servers |
| `mailers` | Delivery of e-mails |
| `pull` | Lower priority tasks such as handling imports, backups, resolving threads, deleting users, forwarding replies |
| `scheduler` | Doing cron jobs like refreshing trending hashtags and cleaning up logs |
| `ingress` | Incoming remote activities. Lower priority than the default queue so local users still see their posts when the server is under load |
The default queues and their priorities are stored in [config/sidekiq.yml](https://github.com/mastodon/mastodon/blob/main/config/sidekiq.yml), but can be overridden by the command-line invocation of Sidekiq, e.g.:
@ -80,7 +123,6 @@ As a solution, it is possible to start different Sidekiq processes for the queue
**Make sure you only have one `scheduler` queue running!!**
## Transaction pooling with pgBouncer {#pgbouncer}
### Why you might need PgBouncer {#pgbouncer-why}
@ -167,10 +209,22 @@ listen_port = 6432
Put `md5` as the `auth_type` (assuming youre using the md5 format in `userlist.txt`):
```ini
auth_type = md5
```
Make sure the `pgbouncer` user is an admin:
```ini
admin_users = pgbouncer
```
**This next part is very important!** The default pooling mode is session-based, but for Mastodon we want transaction-based. In other words, a Postgres connection is created when a transaction is created and dropped when the transaction is done. So youll want to change the `pool_mode` from `session` to `transaction`:
```ini
pool_mode = transaction
```
Next up, `max_client_conn` defines how many connections PgBouncer itself will accept, and `default_pool_size` puts a limit on how many Postgres connections will be opened under the hood. (In PgHero the number of connections reported will correspond to `default_pool_size` because it has no knowledge of PgBouncer.)
The defaults are fine to start, and you can always increase them later:
@ -322,7 +376,11 @@ To reduce the load on your Postgresql server, you may wish to setup hot streamin
* The streaming API server does not issue writes at all, so you can connect it straight to the replica (it is not querying the database very often anyway, so the impact of this is small).
* Use the Makara driver in the web and Sidekiq processes, so that writes go to the master database, while reads go to the replica. Lets talk about that.
You will have to edit the `config/database.yml` file and replace the `production` section as follows:
{{< hint style="warning" >}}
Read replicas are currently not supported for the Sidekiq processes, and using them will lead to failing jobs and data loss.
{{< /hint >}}
You will have to use a separate `config/database.yml` file for the web processes and edit it to replace the `production` section as follows:
```yaml
production:
@ -340,9 +398,8 @@ production:
url: postgresql://db_user:db_password@db_host:db_port/db_name
```
Make sure the URLs point to wherever your PostgreSQL servers are. You can add multiple replicas. You could have a locally installed pgBouncer with configuration to connect to two different servers based on database name, e.g. “mastodon” going to master, “mastodon_replica” going to the replica, so in the file above both URLs would point to the local pgBouncer with the same user, password, host and port, but different database name. There are many possibilities how this could be setup! For more information on Makara, [see their documentation](https://github.com/taskrabbit/makara#databaseyml).
Make sure the URLs point to wherever your PostgreSQL servers are. You can add multiple replicas. You could have a locally installed pgBouncer with configuration to connect to two different servers based on database name, e.g. “mastodon” going to the primary, “mastodon_replica” going to the replica, so in the file above both URLs would point to the local pgBouncer with the same user, password, host and port, but different database name. There are many possibilities how this could be setup! For more information on Makara, [see their documentation](https://github.com/taskrabbit/makara#databaseyml).
{{< hint style="warning" >}}
Sidekiq cannot reliably use read-replicas because even the tiniest replication lag leads to failing jobs due to queued up records not being found.
Make sure the sidekiq processes run with the stock `config/database.yml` to avoid failing jobs and data loss!
{{< /hint >}}

View File

@ -22,7 +22,7 @@ RAILS_ENV=production bin/tootctl help
## Base CLI
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/cli.rb" caption="lib/cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/base.rb" caption="lib/mastodon/cli/base.rb" >}}
---
@ -61,7 +61,7 @@ Show the version of the currently running Mastodon instance.
## Accounts CLI {#accounts}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/accounts_cli.rb" caption="lib/mastodon/accounts_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/accounts.rb" caption="lib/mastodon/cli/accounts.rb" >}}
---
@ -331,7 +331,7 @@ Approve new registrations when instance is in approval mode.
: Local username.
`--number N`
: Approve the N most recent registrations.
: Approve the N earliest pending registrations.
`--all`
: Approve all pending registrations.
@ -345,7 +345,7 @@ Approve new registrations when instance is in approval mode.
## Cache CLI {#cache}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/cache_cli.rb" caption="lib/mastodon/cache_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/cache.rb" caption="lib/mastodon/cli/cache.rb" >}}
---
@ -384,7 +384,7 @@ Update hard-cached counters of TYPE by counting referenced records from scratch.
## Domains CLI {#domains}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/domains_cli.rb" caption="lib/mastodon/domains_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/domains.rb" caption="lib/mastodon/cli/domains.rb" >}}
---
@ -450,7 +450,7 @@ Crawl the known fediverse by using Mastodon REST API endpoints that expose all k
## Email domain blocks CLI {#email-domain-blocks}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/email_domain_blocks_cli.rb" caption="lib/mastodon/email_domain_blocks_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/email_domain_blocks.rb" caption="lib/mastodon/cli/email_domain_blocks.rb" >}}
---
@ -500,7 +500,7 @@ Remove entries from the e-mail domain blocklist.
## Emoji CLI {#emoji}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/emoji_cli.rb" caption="lib/mastodon/emoji_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/emoji.rb" caption="lib/mastodon/cli/emoji.rb" >}}
---
@ -572,7 +572,7 @@ Remove all custom emoji.
## Feeds CLI {#feeds}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/feeds_cli.rb" caption="lib/mastodon/feeds_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/feeds.rb" caption="lib/mastodon/cli/feeds.rb" >}}
---
@ -617,7 +617,7 @@ Remove all home and list feeds from Redis.
## Maintenance CLI {#maintenance}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/maintenance_cli.rb" caption="lib/mastodon/maintenance_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/maintenance.rb" caption="lib/mastodon/cli/maintenance.rb" >}}
---
@ -636,7 +636,7 @@ Fix corrupted database indexes that may have been caused due to changing collati
## Media CLI {#media}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/media_cli.rb" caption="lib/mastodon/media_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/media.rb" caption="lib/mastodon/cli/media.rb" >}}
---
@ -644,14 +644,23 @@ Fix corrupted database indexes that may have been caused due to changing collati
### `tootctl media remove` {#media-remove}
Remove locally cached copies of media attachments from other servers.
Removes locally cached copies of media attachments, avatars or profile headers from other servers. By default, only media attachments are removed.
`--days N`
: How old media attachments have to be before they are removed. Defaults to 7.
: How old media attachments have to be before they are removed. In case of avatars and headers, how old the last webfinger request and update to the user has to be before they are removed. Defaults to 7.
`--concurrency N`
: The number of workers to use for this task. Defaults to N=5.
`--prune-profiles`
: Instead of media attachments, remove locally cached copies of avatars and headers from other servers. Cannot be combined with `--remove-headers`.
`--remove-headers`
: Instead of media attachments, remove locally cached copies of headers from other servers. Cannot be combined with `--prune-profiles`.
`--include-follows`
: Override the default behavior of `--prune-profiles` and `--remove-headers` to remove locally cached copies of avatars (and headers) from other servers, irrespective of follow status (by default, they are only removed from accounts that are not followed by or following anyone locally). Can only be used with `--prune-profiles` or `--remove-headers`.
`--verbose`
: Print additional information while task is processing.
@ -660,7 +669,8 @@ Remove locally cached copies of media attachments from other servers.
**Version history:**\
2.5.0 - added\
2.6.2 - show freed disk space
2.6.2 - show freed disk space\
4.1.0 - added --prune-profiles, --remove-headers, and --include-follows.
---
@ -693,7 +703,7 @@ Scans for files that do not belong to existing media attachments, and remove the
### `tootctl media refresh` {#media-refresh}
Refetch remote media attachments from other servers. You must specify the source of media attachments with either `--status`, `--account`, or `--domain`. If an attachment already exists in the database, it will not be overwritten unless you use `--force`.
Refetch remote media attachments from other servers. You must specify the source of media attachments with either `--status`, `--account`, `--domain`, or `--days`. If an attachment already exists in the database, it will not be overwritten unless you use `--force`.
`--account ACCT`
: String `username@domain` handle of the account
@ -704,6 +714,9 @@ Refetch remote media attachments from other servers. You must specify the source
`--status ID`
: Local numeric ID of the status in the database.
`--days N`
: The number of days to limit this task to.
`--concurrency N`
: The number of workers to use for this task. Defaults to 5.
@ -718,7 +731,8 @@ Refetch remote media attachments from other servers. You must specify the source
**Version history:**\
3.0.0 - added\
3.0.1 - add `--force` and skip already downloaded attachments by default
3.0.1 - add `--force` and skip already downloaded attachments by default\
4.0.0 - add `--days`
---
@ -748,7 +762,7 @@ Prompts for a media URL, then looks up the status where the media is displayed.
## Preview Cards CLI {#preview_cards}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/preview_cards_cli.rb" caption="lib/mastodon/preview_cards_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/preview_cards.rb" caption="lib/mastodon/cli/preview_cards.rb" >}}
---
@ -782,7 +796,7 @@ Remove local thumbnails for preview cards.
## Search CLI {#search}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/search_cli.rb" caption="lib/mastodon/search_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/search.rb" caption="lib/mastodon/cli/search.rb" >}}
---
@ -790,10 +804,10 @@ Remove local thumbnails for preview cards.
### `tootctl search deploy` {#search-deploy}
Create or update an ElasticSearch index and populate it. If ElasticSearch is empty, this command will create the necessary indices and then import data from the database into those indices. This command will also upgrade indices if the underlying schema has been changed since the last run.
Create or update an Elasticsearch index and populate it. If Elasticsearch is empty, this command will create the necessary indices and then import data from the database into those indices. This command will also upgrade indices if the underlying schema has been changed since the last run.
`--batch-size`
: Defaults to 1000. A lower batch size can make ElasticSearch process records more quickly.
: Defaults to 100. A higher batch size can make Elasticsearch process records more quickly, with less load on the PostgreSQL database, but can increase memory pressure on the Elasticsearch nodes during indexing.
`--only INDEX`
: Specify an index name [`accounts`, `tags`, `statuses`] to create or update only that index.
@ -813,7 +827,7 @@ Create or update an ElasticSearch index and populate it. If ElasticSearch is emp
## Settings CLI {#settings}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/settings_cli.rb" caption="lib/mastodon/settings_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/settings.rb" caption="lib/mastodon/cli/settings.rb" >}}
---
@ -857,7 +871,7 @@ Set registration to require approval.
## Statuses CLI {#statuses}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/statuses_cli.rb" caption="lib/mastodon/statuses_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/statuses.rb" caption="lib/mastodon/cli/statuses.rb" >}}
---
@ -886,7 +900,7 @@ This is a computationally heavy procedure that creates extra database indices be
## Upgrade CLI {#upgrade}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/upgrade_cli.rb" caption="lib/mastodon/upgrade_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/upgrade.rb" caption="lib/mastodon/cli/upgrade.rb" >}}
---
@ -903,4 +917,4 @@ Upgrade the storage schema to store all non-local media resources in a top-level
: Print expected results only, without performing any actions.
**Version history:**\
3.1.4 - added
3.1.4 - added

View File

@ -30,3 +30,11 @@ Check that you are specifying the correct environment with `RAILS_ENV=production
## **I encountered a compilation error while executing `RAILS_ENV=production bundle exec rails assets:precompile`, but no more information is given. How to fix it?**
Usually it's because your server ran out of memory while compiling assets. Use a swapfile or increase the swap space to increase the memory capacity. Run `RAILS_ENV=production bundle exec rake tmp:cache:clear` to clear cache, then execute `RAILS_ENV=production bundle exec rails assets:precompile` to compile again. Make sure you clear the cache after a compilation error, or it will show "Everything's OK" but leave the assets unchanged.
## **I am getting this error: `Read-only file system @ dir_s_mkdir`. Why?**
By default, Mastodon makes use of [systemd's sandboxing capabilities](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Sandboxing) in a way that disallows writing outside of `/home/mastodon`. If Mastodon is installed elsewhere, you may need to allow `mastodon-sidekiq` and `mastodon-web` to write to a custom directory:
1. Add parameter `ReadWritePaths` to files `/etc/systemd/system/mastodon-sidekiq.service` and `/etc/systemd/system/mastodon-web.service`. Example - `ReadWritePaths=/example/mastodon/live`.
2. run `systemctl stop mastodon-sidekiq mastodon-web`
3. run `systemctl daemon-reload`
4. run `systemctl start mastodon-sidekiq mastodon-web`

View File

@ -7,9 +7,19 @@ menu:
---
{{< hint style="info" >}}
When a new version of Mastodon comes out, it appears on the [GitHub releases page](https://github.com/mastodon/mastodon/releases). Please mind that running unreleased code from the `master` branch, while possible, is not recommended.
When a new version of Mastodon comes out, it appears on the [GitHub releases page](https://github.com/mastodon/mastodon/releases). Please mind that running unreleased code from the `main` branch, while possible, is not recommended.
{{< /hint >}}
### Automatic update verification {#automated_checks}
Since v4.2.0, Mastodon will automatically check for available updates and notify the users of your server that have the `DevOps` permission.
This happens by fetching `https://api.joinmastodon.org/update-check?version=<current_version>` in the background every 30 minutes. `current_version` omits the build metadata (everything after the first `+`, if there is one, in the version string). For instance, if your version is `4.3.0-beta2+my-fork`, Mastodon will query `https://api.joinmastodon.org/update-check?version=4.3.0-beta2`.
You can change which URL Mastodon queries by setting the `UPDATE_CHECK_URL` environment variable. You can also completely disable this behavior by setting this environment variable to an empty string, although we strongly recommend against doing that unless you are keeping up with Mastodon updates in another way, as Mastodon occasionally releases critical security updates that must be applied in a timely fashion.
### Upgrade steps
Mastodon releases correspond to git tags. Before attempting an upgrade, look up the desired release on the [GitHub releases page](https://github.com/mastodon/mastodon/releases). The page will contain a **changelog** describing everything you need to know about what's different, as well as **specific upgrade instructions**.
To begin, switch to the `mastodon` user:
@ -59,14 +69,14 @@ systemctl reload mastodon-web
The `reload` operation is a zero-downtime restart, also called "phased restart". As such, Mastodon upgrades usually do not require any advance notice to users about planned downtime. In rare cases, you can use the `restart` operation instead, but there will be a (short) felt interruption of service for your users.
{{< /hint >}}
Rarely, the **streaming API** server is also updated and requires a restart:
The **streaming API** server is also updated and requires a restart, doing so will result in all connected clients being disconnected, which can increase load on your server:
```bash
systemctl restart mastodon-streaming
```
{{< hint style="danger" >}}
The streaming API server is updated very rarely, and in most releases, does *not* require a restart. Restarting the streaming API leads to an increased load on your server as disconnected clients attempt to reconnect or poll the REST API instead, so avoid it whenever you can.
Restarting the streaming API leads to an increased load on your server as disconnected clients attempt to reconnect or poll the REST API instead, so avoid it whenever you can.
{{< /hint >}}
{{< hint style="success" >}}

View File

@ -32,7 +32,27 @@ With that said, because IDs are string representations of numbers, they can stil
## Paginating through API responses {#pagination}
Many API methods allow you to paginate for more information, using parameters such as `limit`, `max_id`, `min_id`, and `since_id`. However, some of these API methods operate on entity IDs that are not publicly exposed in the API response, and are only known to the backend and the database. (This is usually the case for entities that reference other entities, such as Follow entities which reference Accounts, or Favourite entities which reference Statuses, etc.)
Many API methods allow you to paginate for more information, using parameters such as `limit`, `max_id`, `min_id`, and `since_id`.
limit
: The maximum number of results to return. Usually, there is a default limit and a maximum limit; these will vary according to the API method.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward. (Available since v2.6.0.)
For example, we might fetch `https://mastodon.example/api/v1/accounts/1/statuses` with certain parameters, and we will get the following results in the following cases:
- Setting `?max_id=1` will return no statuses, since there are no statuses with an ID earlier than `1`.
- Setting `?since_id=1` will return the latest statuses, since there have been many statuses since `1`.
- Setting `?min_id=1` will return the oldest statuses, as `min_id` sets the cursor.
Some API methods operate on entity IDs that are not publicly exposed in the API response, and are only known to the backend and the database. (This is usually the case for entities that reference other entities, such as Follow entities which reference Accounts, or Favourite entities which reference Statuses, etc.)
To get around this, Mastodon may return links to a "prev" and "next" page. These links are made available via the HTTP `Link` header on the response. Consider the following fictitious API call:
@ -40,7 +60,7 @@ To get around this, Mastodon may return links to a "prev" and "next" page. These
GET https://mastodon.example/api/v1/endpoint HTTP/1.1
Authorization: Bearer token
Link: <https://mastodon.example/api/v1/endpoint?max_id=7163058>; rel="next", <https://mastodon.example/api/v1/endpoint?since_id=7275607>; rel="prev"
Link: <https://mastodon.example/api/v1/endpoint?max_id=7163058>; rel="next", <https://mastodon.example/api/v1/endpoint?min_id=7275607>; rel="prev"
[
{
// some Entity
@ -123,9 +143,9 @@ If `whole_word` is true, the client app should do the following:
Please check `app/javascript/mastodon/selectors/index.js` and `app/lib/feed_manager.rb` in the Mastodon source code for more details.
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/javascript/mastodon/selectors/index.js" caption="app/javascript/mastodon/selectors/index.js" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/javascript/mastodon/selectors/index.js" caption="app/javascript/mastodon/selectors/index.js" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/lib/feed_manager.rb" caption="app/lib/feed_manager.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/lib/feed_manager.rb" caption="app/lib/feed_manager.rb" >}}
## Focal points for cropping media thumbnails {#focal-points}

View File

@ -109,7 +109,7 @@ With our OAuth token for the authorized user, we can now perform any action as t
* See [/api/v2/search]({{< relref "methods/search#v2" >}}) for querying resources.
* See [/api/v1/suggestions]({{< relref "methods/suggestions" >}}) for suggested accounts to follow.
### Use safety features {#safety}
### User safety features {#safety}
* See [/api/v1/filters]({{< relref "methods/filters" >}}) for managing filtered keywords.
* See [/api/v1/domain_blocks]({{< relref "methods/domain_blocks" >}}) for managing blocked domains.

View File

@ -113,7 +113,7 @@ As JSON, hashes are formatted like so:
{
"source": {
"privacy": "public",
"language", "en"
"language": "en"
}
}
```

View File

@ -1,18 +1,22 @@
---
title: Libraries and implementations
description: Interface with the Mastodon API in the programming language of your choice.
description: Code, libraries and SDKs for the Mastodon API in a range of programming languages.
menu:
docs:
weight: 60
parent: client
---
## Apex (Salesforce) {#apex-salesforce}
Thank you to our awesome developer community, for supporting the project with a wide range of implementations of the API. If you have built a library or SDK for the Mastodon API, [let us know](https://github.com/mastodon/mastodon/discussions) about it, and it may be included below in a future update.
* [apex-mastodon](https://github.com/tzmfreedom/apex-mastodon)
Remember to check how recently the library was updated, and whether it includes the API features you may want to use.
## Arduino / ESP32 / IoT {#arduino-iot}
* [lyuba](https://github.com/ringtailsoftware/lyuba)
## C# (.NET Standard) {#c-net-standard}
* [MastodonAPI](https://github.com/golf1052/MastodonAPI)
* [Mastodot](https://github.com/yamachu/Mastodot)
* [Mastonet](https://github.com/glacasa/Mastonet)
* [TootNet](https://github.com/cucmberium/TootNet)
@ -23,26 +27,35 @@ menu:
* [mastodonpp](https://schlomp.space/tastytea/mastodonpp)
## Crystal {#crystal}
* [mastodon.cr](https://github.com/decors/mastodon.cr)
## Common Lisp {#common-lisp}
* [mastodon-cl](https://github.com/compufox/mastodon-cl)
* [tooter](https://github.com/Shinmera/tooter)
## Crystal {#crystal}
* [mastodon-api-crystal](https://github.com/renatolond/mastodon-api-crystal)
## Dart
* [mastodon](https://pub.dev/packages/mastodon)
* [mastodon-api](https://github.com/mastodon-dart/mastodon-api)
* [mastodon-oauth](https://github.com/mastodon-dart/mastodon-oauth2)
* [mastodon](https://github.com/mykdavies/Mastodon)
* [dartodon](https://github.com/darkcl/dartodon)
## Elixir {#elixir}
* [hunter](https://github.com/milmazz/hunter)
## Erlang {#erlang}
* [masterldon](https://github.com/igb/masterldon)
## Go {#go}
* [go-mastodon](https://github.com/mattn/go-mastodon)
* [madon](https://github.com/McKael/madon)
* [go-mastodon-api](https://github.com/aaronland/go-mastodon-api)
## Haskell {#haskell}
@ -50,10 +63,13 @@ menu:
## Java {#java}
* [mastodon4j](https://github.com/sys1yagi/mastodon4j)
* [BigBone](https://github.com/andregasser/bigbone)
* [Mastodon4J](https://github.com/Mastodon4J/Mastodon4J)
* [mastodon-jfx](https://github.com/wakingrufus/mastodon-jfx)
## JavaScript {#javascript}
* [megalodon](https://github.com/h3poteto/megalodon)
* [masto.js](https://github.com/neet/masto.js)
* [libodonjs](https://github.com/Zatnosk/libodonjs)
@ -63,29 +79,51 @@ menu:
## JavaScript (Node.js) {#javascript-node-js}
* [node-mastodon](https://github.com/jessicahayley/node-mastodon)
* [mastodon-api](https://github.com/vanita5/mastodon-api)
## Kotlin {#kotlin}
* [BigBone](https://github.com/andregasser/bigbone)
* [mastodonk](https://github.com/outadoc/mastodonk)
## Nim {#nim}
* [Mastonim](https://github.com/matrix07012/Mastonim)
## Objective-C {#objective-c}
* [Cocotodon](https://github.com/shibafu528/Cocotodon)
## Perl {#perl}
* [Mastodon::Client](https://metacpan.org/pod/Mastodon::Client)
## PHP {#php}
* [Mastodon API for Laravel](https://github.com/kawax/laravel-mastodon-api)
* [Composer based php API wrapper](https://github.com/r-daneelolivaw/mastodon-api-php)
* [MastodonOAuthPHP](https://github.com/TheCodingCompany/MastodonOAuthPHP)
* [mastodon-api-client](https://github.com/vazaha-nl/mastodon-api-client)
* [Phediverse Mastodon REST Client](https://github.com/phediverse/mastodon-rest)
* [TootoPHP](https://framagit.org/MaxKoder/TootoPHP)
* [oauth2-mastodon](https://github.com/lrf141/oauth2-mastodon)
* [MastodonBotPHP](https://github.com/Eleirbag89/MastodonBotPHP)
* [mastodon-api-php-oauth](https://github.com/yks118/Mastodon-api-php-oauth)
* [mastodon-api-php](https://github.com/colorfield/mastodon-api-php)
* [Mastodon API for Laravel](https://github.com/kawax/laravel-mastodon-api)
* [Mastodon for Drupal](https://www.drupal.org/project/mastodon)
* [Mastodon for Socialite](https://github.com/kawax/socialite-mastodon)
## PowerShell {#powershell}
* [Mastodon](https://github.com/JB405/Mastodon)
## Python {#python}
* [Mastodon.py](https://github.com/halcy/Mastodon.py)
* [mastopy](https://gitlab.com/spla/mastopy)
## R {#r}
* [mastodon](https://github.com/ThomasChln/mastodon)
* [rtoot](https://github.com/schochastics/rtoot)
## Ruby {#ruby}
@ -93,8 +131,8 @@ menu:
## Rust {#rust}
* [mammut](https://github.com/Aaronepower/mammut) (unmaintained)
* [elefren](https://github.com/DeeUnderscore/elefren) (unmaintained)
* [megalodon-rs](https://github.com/h3poteto/megalodon-rs)
* [mastodon-async](https://github.com/dscottboggs/mastodon-async)
## Scala {#scala}
@ -104,9 +142,17 @@ menu:
### Guile {#guile}
* [elefan](https://codeberg.org/WammKD/Guile-Mastodon)
* [Guile-Mastodon](https://codeberg.org/WammKD/Guile-Mastodon)
## Swift {#swift}
* [MastodonKit](https://github.com/ornithocoder/MastodonKit)
* [Mastodon.swift](https://github.com/Swiftodon/Mastodon.swift)
* [MastodonKit](https://github.com/MastodonKit/MastodonKit)
* [tootsdk](https://github.com/tootsdk/tootsdk)
* [MastodonAPI](https://github.com/li-bei/MastodonAPI)
## TypeScript {#typescript}
* [tsl-mastodon](https://github.com/typescriptlibs/tsl-mastodon-api)

View File

@ -70,5 +70,4 @@ The following overview should not be seen as complete or authoritative, but as a
All locale files are normalized to ensure consistent formatting and key order, which minimizes changesets in version control.
- Run `bundle exec i18n-tasks normalize` to normalize server-side translations
- Run `yarn run manage:translations` to normalize client-side translations
- Run `yarn run i18n:extract` to extract and normalize client-side translations into `en.json`

View File

@ -7,7 +7,7 @@ menu:
parent: dev
---
If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you should send the report to **hello@joinmastodon.org**. We will gladly reward such reports in proportion to the severity of the issue through our OpenCollective fund.
If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you should send the report to **security@joinmastodon.org**. We will gladly reward such reports in proportion to the severity of the issue through our OpenCollective fund.
You should *not* report such issues on GitHub or in other public spaces to give us time to publish a fix for the issue without exposing Mastodon's users to increased risk.

View File

@ -7,7 +7,7 @@ menu:
parent: dev
---
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/config/routes.rb" caption="config/routes.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/config/routes.rb" caption="config/routes.rb" >}}
## Explanation of routes {#routes}

View File

@ -65,7 +65,7 @@ You can now create the databases `mastodon_development` and `mastodon_test`, loa
rails db:setup
```
You can now launch `http://localhost:3000` in your browser and log in with the default admin user (`admin@localhost:3000` / `mastodonadmin`).
You can now launch `http://localhost:3000` in your browser and log in with the default admin user (`admin@localhost` / `mastodonadmin`).
{{<hint style="warning">}}
By default, Mastodon will run on port 3000. If you configure a different port for it, the generated admin account will use that number as well.
@ -82,6 +82,14 @@ foreman start
This will start processes defined in `Procfile.dev`, which will give you: A Rails server, a Webpack server, a streaming API server, and Sidekiq. Of course, you can run any of those things stand-alone depending on your needs.
## Working with emails in development
In development mode, Mastodon will use a gem called [Letter Opener](https://github.com/ryanb/letter_opener) for "sending" emails, which allows you to debug emails in your browser, without actually having to send emails via an SMTP server.
In order to work with emails, you'll need Sidekiq, Redis and PostgreSQL running, and then emails can be viewed by visiting: `http://localhost:3000/letter_opener/`
If you're developing in docker, you'll need to set the `REMOTE_DEV=true` environment variable.
## Useful commands for testing {#testing}
`rspec`
@ -102,4 +110,4 @@ This will start processes defined in `Procfile.dev`, which will give you: A Rail
: Update Javascript packages and install any new dependencies
`RAILS_ENV=development rails db:migrate`
: Run new database migrations for your development instance's database
: Run new database migrations for your development instance's database

View File

@ -48,7 +48,7 @@ aliases: [
"followers_count": 547,
"following_count": 404,
"statuses_count": 28468,
"last_status_at": "2019-11-17T00:02:23.693Z",
"last_status_at": "2019-11-17",
"emojis": [
{
"shortcode": "ms_rainbow_flag",
@ -442,8 +442,8 @@ aliases: [
{{< page-relref ref="methods/accounts" caption="accounts API methods" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/serializers/rest/account_serializer.rb" caption="app/serializers/rest/account_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/account_serializer.rb" caption="app/serializers/rest/account_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/serializers/rest/credential_account_serializer.rb" caption="app/serializers/rest/credential_account_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/credential_account_serializer.rb" caption="app/serializers/rest/credential_account_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/serializers/rest/muted_account_serializer.rb" caption="app/serializers/rest/muted_account_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/muted_account_serializer.rb" caption="app/serializers/rest/muted_account_serializer.rb" >}}

View File

@ -210,4 +210,4 @@ aliases: [
{{< page-relref ref="methods/admin/accounts" caption="admin/accounts API methods" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/serializers/rest/admin/account_serializer.rb" caption="app/serializers/rest/admin/account_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/account_serializer.rb" caption="app/serializers/rest/admin/account_serializer.rb" >}}

View File

@ -77,7 +77,7 @@ Daily retention data for the week between 2022-09-08 and 2022-09-14, given that
"value": "1"
}
]
},
}
```
## Attributes

View File

@ -165,7 +165,7 @@ Show dimensional data about how much space is used by each software in your serv
"human_value": "0 Bytes"
}
]
},
}
```
### `software_versions` {#software_versions}

View File

@ -53,4 +53,4 @@ aliases: [
{{< page-relref page="methods/admin/domain_allows" caption="admin/domain_allows API methods" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/domain_allows_serializer.rb" caption="app/serializers/rest/admin/domain_allows_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/domain_allow_serializer.rb" caption="app/serializers/rest/admin/domain_allow_serializer.rb" >}}

View File

@ -104,4 +104,4 @@ aliases: [
{{< page-relref page="methods/admin/domain_blocks" caption="admin/domain_blocks API methods" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/domain_blocks_serializer.rb" caption="app/serializers/rest/admin/domain_blocks_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/domain_block_serializer.rb" caption="app/serializers/rest/admin/domain_block_serializer.rb" >}}

View File

@ -118,4 +118,4 @@ aliases: [
{{< page-relref page="methods/admin/email_domain_blocks" caption="admin/email_domain_blocks API methods" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/email_domain_blocks_serializer.rb" caption="app/serializers/rest/admin/email_domain_blocks_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/email_domain_block_serializer.rb" caption="app/serializers/rest/admin/email_domain_block_serializer.rb" >}}

View File

@ -80,4 +80,4 @@ aliases: [
{{< page-relref page="methods/admin/ip_blocks" caption="admin/ip_blocks API methods" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/ip_blocks_serializer.rb" caption="app/serializers/rest/admin/ip_blocks_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/ip_block_serializer.rb" caption="app/serializers/rest/admin/ip_block_serializer.rb" >}}

View File

@ -170,7 +170,7 @@ aliases: [
{{< page-relref page="methods/admin/reports" caption="admin/reports API methods">}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/serializers/rest/admin/report_serializer.rb" caption="app/serializers/rest/admin/report_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/admin/report_serializer.rb" caption="app/serializers/rest/admin/report_serializer.rb" >}}

View File

@ -39,13 +39,6 @@ aliases: [
0.9.9 - added\
3.5.1 - this property is now nullable
### `vapid_key` {#vapid_key}
**Description:** Used for Push Streaming API. Returned with [POST /api/v1/apps]({{< relref "methods/apps#create" >}}). Equivalent to [WebPushSubscription#server_key]({{< relref "entities/WebPushSubscription#server_key" >}})\
**Type:** String\
**Version history:**\
2.8.0 - added
### `client_id` {{%optional%}} {#client_id}
**Description:** Client ID key, to be used for obtaining OAuth tokens\
@ -60,10 +53,20 @@ aliases: [
**Version history:**\
0.9.9 - added
## Deprecated attributes
### `vapid_key` {#vapid_key}
**Description:** Used for Push Streaming API. Returned with [POST /api/v1/apps]({{< relref "methods/apps#create" >}}). Equivalent to [WebPushSubscription#server_key]({{< relref "entities/WebPushSubscription#server_key" >}}) and [Instance#vapid_public_key]({{< relref "entities/Instance#vapid_public_key" >}})\
**Type:** String\
**Version history:**\
2.8.0 - added
4.3.0 - deprecated pending removal
## See also
{{< page-relref ref="methods/apps" caption="apps API methods" >}}
{{< page-relref ref="entities/Status#application" caption="Status (`application` attribute)" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/serializers/rest/application_serializer.rb" caption="app/serializers/rest/application_serializer.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/application_serializer.rb" caption="app/serializers/rest/application_serializer.rb" >}}

View File

@ -117,7 +117,7 @@ Error: There was a temporary problem serving your request, please try again. App
## See also
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/controllers/api/base_controller.rb" caption="app/controllers/api/base_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/base_controller.rb" caption="app/controllers/api/base_controller.rb" >}}

View File

@ -50,7 +50,7 @@ aliases: [
### `statuses_count` {#statuses_count}
**Description:** The number of authored statuses containing this hashtag.\
**Type:** Number\
**Type:** Integer\
**Version history:**\
3.0.0 - added

View File

@ -53,7 +53,7 @@ aliases: [
### `status_matches` {#status_matches}
**Description:** The status ID within the filter that was matched.\
**Type:** {{<nullable>}} String, or null\
**Type:** {{<nullable>}} Array of String, or null\
**Version history:**\
4.0.0 - added

View File

@ -41,6 +41,9 @@ aliases: [
"urls": {
"streaming": "wss://mastodon.social"
},
"vapid": {
"public_key": "BCkMmVdKDnKYwzVCDC99Iuc9GvId-x7-kKtuHnLgfF98ENiZp_aj-UNthbCdI70DqN1zUVis-x0Wrot2sBagkMc="
},
"accounts": {
"max_featured_tags": 10
},
@ -290,6 +293,12 @@ aliases: [
**Version history:**\
4.0.0 - added
### `configuration[vapid][public_key]` (#vapid_public_key)
**Description:** The instances VAPID public key, used for push notifications, the same as [WebPushSubscription#server_key]({{< relref "entities/WebPushSubscription#server_key" >}}).\
**Type:** String\
**Version history:**\
4.3.0 - added
#### `configuration[accounts]` {#accounts}
**Description:** Limits related to accounts.\

View File

@ -212,7 +212,7 @@ More importantly, there may be another topl-level `focus` Hash object on images
### `description` {#description}
**Description:** Alternate text that describes what is in the media attachment, to be used for the visually impaired or when media attachments do not load.\
**Type:** String\
**Type:** {{<nullable>}} String, or null if alternate text was not provided for the media attachment\
**Version history:**\
2.0.0 - added

View File

@ -19,18 +19,20 @@ aliases: [
## Example
```json
{
"name": "bongoCat",
"count": 9,
"me": false,
"url": "https://files.mastodon.social/custom_emojis/images/000/067/715/original/fdba57dff7576d53.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/067/715/static/fdba57dff7576d53.png"
},
{
"name": "🤔",
"count": 1,
"me": true
}
[
{
"name": "bongoCat",
"count": 9,
"me": false,
"url": "https://files.mastodon.social/custom_emojis/images/000/067/715/original/fdba57dff7576d53.png",
"static_url": "https://files.mastodon.social/custom_emojis/images/000/067/715/static/fdba57dff7576d53.png"
},
{
"name": "🤔",
"count": 1,
"me": true
}
]
```
## Attributes

View File

@ -134,6 +134,6 @@ aliases: [
## See also
{{< page-relref ref="methods/accounts#relationships" caption="POST /api/v1/accounts/relationships" >}}
{{< page-relref ref="methods/accounts#relationships" caption="GET /api/v1/accounts/relationships" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/serializers/rest/relationship_serializer.rb" caption="app/serializers/rest/relationship_serializer.rb" >}}

View File

@ -19,12 +19,9 @@ aliases: [
"id": 3,
"name": "Owner",
"color": "#ff3838",
"position": 1000,
"permissions": 1,
"highlighted": true,
"created_at": "2022-09-08T22:48:07.983Z",
"updated_at": "2022-09-08T22:48:07.983Z"
},
"permissions": 1048575,
"highlighted": true
}
```
## Attributes
@ -50,13 +47,6 @@ aliases: [
**Version history:**\
4.0.0 - added
### `position` {#position}
**Description:** An index for the role's position. The higher the position, the more priority the role has over other roles.\
**Type:** Integer\
**Version history:**\
4.0.0 - added
### `permissions` {#permissions}
**Description:** A bitmask that represents the sum of all permissions granted to the role.\
@ -71,20 +61,6 @@ aliases: [
**Version history:**\
4.0.0 - added
### `created_at` {#created_at}
**Description:** The date that the role was created.\
**Type:** String (ISO 8601 Datetime)\
**Version history:**\
4.0.0 - added
### `updated_at` {#created_at}
**Description:** The date that the role was updated.\
**Type:** String (ISO 8601 Datetime)\
**Version history:**\
4.0.0 - added
## Permission flags
To determine the permissions available to a certain role, convert the `permissions` attribute to binary and compare from the least significant bit upwards. For convenience (and to prevent the terms from growing too long), permissions will be presented below using hexadecimal values.

View File

@ -78,7 +78,7 @@ aliases: [
### `account` {#account}
**Description:** The account that published this revision.\
**Type:** Account\
**Type:** [Account]({{<relref "entities/Account">}})\
**Version history:**\
3.5.0 - added

View File

@ -745,14 +745,14 @@ Authorization
##### Query parameters
max_id
: String. Return results older than this ID
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than this ID
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than this ID
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 20 statuses. Max 40 statuses.
@ -767,7 +767,7 @@ exclude_reblogs
: Boolean. Filter out boosts from the response.
pinned
: Boolean. Filter for pinned statuses only.
: Boolean. Filter for pinned statuses only. Defaults to false, which includes all statuses. Pinned statuses do not receive special priority in the order of the returned results.
tagged
: String. Filter for statuses using a specific hashtag.
@ -1940,7 +1940,8 @@ Find out whether a given account is followed, blocked, muted, etc.
**Returns:** Array of [Relationship]({{< relref "entities/Relationship">}})\
**OAuth:** User token + `read:follows`\
**Version history:**\
0.0.0 - added
0.0.0 - added\
4.3.0 - added `with_suspended` parameter
#### Request
##### Headers
@ -1951,7 +1952,10 @@ Authorization
##### Query parameters
id[]
: Array. Check relationships for the provided account IDs.
: Array of String. Check relationships for the provided account IDs.
with_suspended
: Boolean. Whether relationships should be returned for suspended users, defaults to false.
#### Response
##### 200: OK
@ -2322,4 +2326,4 @@ Token does not have an authorized user
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/accounts/statuses_controller.rb" caption="app/controllers/api/v1/accounts/statuses_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/models/account_statuses_filter.rb" caption="app/models/account_statuses_filter.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/models/account_statuses_filter.rb" caption="app/models/account_statuses_filter.rb" >}}

View File

@ -83,14 +83,14 @@ ip
staff
: Boolean. Filter for staff accounts?
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 100 accounts. Max 200 accounts.
@ -233,14 +233,14 @@ email
ip
: String. Lookup users with this IP address.
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 100 accounts. Max 200 accounts.
@ -686,7 +686,7 @@ POST /api/v1/admin/accounts/:id/action HTTP/1.1
Perform an action against an account and log this action in the moderation history. Also resolves any open reports against this account.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `admin:write:accounts`\
**Permissions:** Manage Users, Manage Reports\
**Version history:**\

View File

@ -94,6 +94,11 @@ GET /api/v1/admin/canonical_email_blocks/:id HTTP/1.1
#### Request
##### Path parameters
:id
: {{<required>}} String. The ID of the Admin::CanonicalEmailBlock in the database.
##### Headers
Authorization
@ -262,6 +267,11 @@ DELETE /api/v1/admin/canonical_email_blocks/:id HTTP/1.1
#### Request
##### Path parameters
:id
: {{<required>}} String. The ID of the Admin::CanonicalEmailBlock in the database.
##### Headers
Authorization

View File

@ -128,7 +128,7 @@ DELETE /api/v1/conversations/:id HTTP/1.1
Removes a conversation from your list of conversations.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:conversations`\
**Version history:**\
2.6.0 - added

View File

@ -90,7 +90,7 @@ Block a domain to:
- remove all followers from it
- prevent following new users from it (but does not remove existing follows)
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:blocks` or `follow`\
**Version:**\
1.4.0 - added
@ -154,7 +154,7 @@ DELETE /api/v1/domain_blocks HTTP/1.1
Remove a domain block, if it exists in the user's array of blocked domains.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:blocks` or `follow`\
**Version history:**\
1.4.0 - added

View File

@ -21,10 +21,10 @@ aliases: [
## Resend confirmation email {#confirmation}
```http
POST /api/v1/emails/confirmation HTTP/1.1
POST /api/v1/emails/confirmations HTTP/1.1
```
**Returns:** Empty object\
**Returns:** Empty\
**OAuth:** User token issued to the client that created the unconfirmed user\
**Version history:**\
3.4.0 - added
@ -73,4 +73,4 @@ Alternatively, the user has already confirmed their email.
{{< page-relref ref="methods/accounts#create" caption="POST /api/v1/accounts" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/emails/confirmations_controller.rb" caption="app/controllers/api/v1/emails/confirmations_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/emails/confirmations_controller.rb" caption="app/controllers/api/v1/emails/confirmations_controller.rb" >}}

View File

@ -29,8 +29,7 @@ Accounts that the user is currently featuring on their profile.
**Returns:** Array of [Account]({{< relref "entities/account" >}})\
**OAuth:** User token + `read:accounts`\
**Version history:**\
2.5.0 - added\
3.3.0 - both `min_id` and `max_id` can be used at the same time now
2.5.0 - added
#### Request

View File

@ -133,7 +133,7 @@ DELETE /api/v1/featured_tags/:id HTTP/1.1
Stop promoting a hashtag on your profile.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:accounts`\
**Version history:**\
3.0.0 - added

View File

@ -16,7 +16,7 @@ aliases: [
## Server-side (v2) methods {#v2}
Since Mastodon 3.6, filters can contain multiple keywords and are matched server-side. Clients apply the filter action based on [the status's `filtered` attribute]({{< relref "entities/Status#filtered" >}}).
Since Mastodon 4.0, filters can contain multiple keywords and are matched server-side. Clients apply the filter action based on [the status's `filtered` attribute]({{< relref "entities/Status#filtered" >}}).
---
@ -206,7 +206,7 @@ keywords_attributes[][keyword]
: String. A keyword to be added to the newly-created filter group.
keywords_attributes[][whole_word]
: String. Whether the keyword should consider word boundaries.
: Boolean. Whether the keyword should consider word boundaries.
<!-- TODO: Remove when https://github.com/mastodon/mastodon/issues/21727 is fixed
keywords_attributes[][id]
@ -330,7 +330,7 @@ keywords_attributes[][keyword]
: String. A keyword to be added to the newly-created filter group.
keywords_attributes[][whole_word]
: String. Whether the keyword should consider word boundaries.
: Boolean. Whether the keyword should consider word boundaries.
keywords_attributes[][id]
: String. Provide the ID of an existing keyword to modify it, instead of creating a new keyword.
@ -403,7 +403,7 @@ DELETE /api/v2/filters/:id HTTP/1.1
Delete a filter group with the given id.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:filters`\
**Version history:**\
4.0.0 - added
@ -730,7 +730,7 @@ DELETE /api/v2/filters/keywords/:id HTTP/1.1
Deletes the given filter keyword.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:filters`\
**Version history:**\
4.0.0 - added
@ -863,6 +863,11 @@ Add a status filter to the current filter group.
Authorization
: {{<required>}} Provide this header with `Bearer <user token>` to gain authorized access to this API method.
##### Form data parameters
status_id
: {{<required>}} String. The status ID to be added to the filter group.
#### Response
##### 200: OK
@ -1012,7 +1017,7 @@ FilterStatus is not owned by you or does not exist
## Client-side (v1) methods {#v1}
Prior to Mastodon 3.6, matching filters was done client-size and filters could only contain one phrase to filter against.
Prior to Mastodon 4.0, matching filters was done client-size and filters could only contain one phrase to filter against.
---
@ -1344,7 +1349,7 @@ If context is not provided properly:
DELETE /api/v1/filters/:id HTTP/1.1
```
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:filters`\
**Version history:**\
2.4.3 - added\
@ -1403,4 +1408,4 @@ Filter does not exist or is not owned by you
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/filters/statuses_controller.rb" caption="app/controllers/api/v1/filters/statuses_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/filters_controller.rb" caption="app/controllers/api/v1/filters_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/filters_controller.rb" caption="app/controllers/api/v1/filters_controller.rb" >}}

View File

@ -27,8 +27,7 @@ GET /api/v1/follow_requests HTTP/1.1
**Returns:** Array of [Account]({{< relref "entities/account" >}})\
**OAuth:** User token + `read:follows` or `follow`\
**Version history:**\
0.0.0 - added\
3.3.0 - both `min_id` and `max_id` can be used at the same time now
0.0.0 - added
#### Request

View File

@ -25,7 +25,7 @@ GET /api/v2/instance
Obtain general information about the server.
**Returns:** [V1::Instance]({{< relref "entities/instance" >}})\
**Returns:** [Instance]({{< relref "entities/Instance" >}})\
**OAuth:** Public\
**Version history:**\
4.0.0 - added
@ -61,6 +61,9 @@ Obtain general information about the server.
"urls": {
"streaming": "wss://mastodon.social"
},
"vapid": {
"public_key": "BCkMmVdKDnKYwzVCDC99Iuc9GvId-x7-kKtuHnLgfF98ENiZp_aj-UNthbCdI70DqN1zUVis-x0Wrot2sBagkMc="
},
"accounts": {
"max_featured_tags": 10
},
@ -496,7 +499,7 @@ GET /api/v1/instance HTTP/1.1
Obtain general information about the server.
**Returns:** [V1::Instance]({{< relref "entities/instance" >}})\
**Returns:** [V1::Instance]({{< relref "entities/V1_Instance" >}})\
**OAuth:** Public\
**Version history:**\
1.1.0 - added\
@ -650,4 +653,4 @@ Obtain general information about the server.
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/instances/peers_controller.rb" caption="app/controllers/api/v1/instances/peers_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/instances/rules_controller.rb" caption="app/controllers/api/v1/instances/rules_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/instances/rules_controller.rb" caption="app/controllers/api/v1/instances/rules_controller.rb" >}}

View File

@ -50,12 +50,14 @@ Use `id` as a parameter for related API calls.
{
"id": "12249",
"title": "Friends",
"replies_policy": "followed"
"replies_policy": "followed",
"exclusive": false
},
{
"id": "13585",
"title": "test",
"replies_policy": "list"
"replies_policy": "list",
"exclusive": true
}
]
```
@ -106,7 +108,8 @@ The list 12249 exists and is owned by you
{
"id": "12249",
"title": "Friends",
"replies_policy": "followed"
"replies_policy": "followed",
"exclusive": false
}
```
@ -144,7 +147,8 @@ Create a new list.
**OAuth:** User token + `write:lists`\
**Version history:**\
2.1.0 - added\
3.3.0 - added `replies_policy`
3.3.0 - added `replies_policy`\
4.2.0 - added `exclusive`
#### Request
##### Headers
@ -160,6 +164,9 @@ title
replies_policy
: String. One of `followed`, `list`, or `none`. Defaults to `list`.
exclusive
: Boolean. Whether members of this list need to get removed from the “Home” feed
#### Response
##### 200: OK
@ -169,7 +176,8 @@ A sample list was created with a `title` of "test".
{
"id": "13585",
"title": "test",
"replies_policy": "list"
"replies_policy": "list",
"exclusive": false
}
```
@ -238,6 +246,9 @@ title
replies_policy
: String. One of `followed`, `list`, or `none`. Defaults to `list`.
exclusive
: Boolean. Whether members of this list need to get removed from the “Home” feed
#### Response
##### 200: OK
@ -247,7 +258,8 @@ The `title` of list 13585 was successfully updated to "testing"
{
"id": "13585",
"title": "test",
"replies_policy": "list"
"replies_policy": "list",
"exclusive": false
}
```
@ -287,7 +299,7 @@ If the `replies_policy` is not understood:
DELETE /api/v1/lists/:id HTTP/1.1
```
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:lists`\
**Version history:**\
2.1.0 - added
@ -449,7 +461,7 @@ POST /api/v1/lists/:id/accounts HTTP/1.1
Add accounts to the given list. Note that the user must be following these accounts.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:lists`\
**Version history:**\
2.1.0 - added
@ -518,7 +530,7 @@ DELETE /api/v1/lists/:id/accounts HTTP/1.1
Remove accounts from the given list.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:lists`\
**Version history:**\
2.1.0 - added
@ -577,4 +589,4 @@ List is not owned by you or does not exist
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/lists_controller.rb" caption="app/controllers/api/v1/lists_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/lists/accounts_controller.rb" caption="app/controllers/api/v1/lists/accounts_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/lists/accounts_controller.rb" caption="app/controllers/api/v1/lists/accounts_controller.rb" >}}

View File

@ -30,7 +30,7 @@ Accounts the user has muted.
**OAuth:** User token + `read:mutes` or `follow`\
**Version history:**\
0.0.0 - added\
3.3.0 - added `mute_expires_at`. both `min_id` and `max_id` can be used at the same time now
3.3.0 - added `mute_expires_at`
#### Request
##### Headers

View File

@ -57,14 +57,14 @@ Authorization
##### Query parameters
max_id
: String. Return results older than this ID
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than this ID
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than this ID
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 15 notifications. Max 30 notifications.
@ -262,7 +262,7 @@ POST /api/v1/notifications/clear HTTP/1.1
Clear all notifications from the server.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:notifications`\
**Version history:**\
0.0.0 - added
@ -303,7 +303,7 @@ POST /api/v1/notifications/:id/dismiss HTTP/1.1
Dismiss a single notification from the server.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:notifications`\
**Version history:**\
1.3.0 - added
@ -350,7 +350,7 @@ POST /api/v1/notifications/dismiss HTTP/1.1
Dismiss a single notification from the server.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:notifications`\
**Version history**:\
0.0.0 - available\

View File

@ -156,7 +156,7 @@ POST /oauth/revoke HTTP/1.1
Revoke an access token to make it no longer valid for use.
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** Public\
**Version history:**\
x.x.x - added

View File

@ -0,0 +1,178 @@
---
title: profile API methods
description: Methods concerning profiles.
menu:
docs:
weight: 20
name: profile
parent: methods
identifier: methods-profile
---
<style>
#TableOfContents ul ul ul {display: none}
</style>
## Delete profile avatar
```http
DELETE /api/v1/profile/avatar HTTP/1.1
```
**Returns:** [CredentialAccount]({{< relref "entities/Account#CredentialAccount">}})\
**OAuth**: User token + `write:accounts`\
**Version history:**\
4.2.0 - added
Deletes the avatar associated with the user's profile.
#### Request
##### Headers
Authorization
: {{<required>}} Provide this header with `Bearer <user token>` to gain authorized access to this API method.
##### Path parameters
#### Response
##### 200: OK
The avatar was successfully deleted from the user's profile. If there were no avatar associated with the profile, the response will still indicate a successful deletion.
```json
{
"id": "110357222516183152",
"username": "rob",
"acct": "rob",
"display_name": "",
"locked": false,
"bot": false,
"discoverable": false,
"group": false,
"created_at": "2023-05-12T00:00:00.000Z",
"note": "",
"url": "http://localhost:3000/@rob",
"uri": "http://localhost:3000/users/rob",
"avatar": "http://localhost:3000/avatars/original/missing.png",
"avatar_static": "http://localhost:3000/avatars/original/missing.png",
"header": "http://localhost:3000/system/accounts/headers/110/357/222/516/183/152/original/0cd99648c23005ed.png",
"header_static": "http://localhost:3000/system/accounts/headers/110/357/222/516/183/152/original/0cd99648c23005ed.png",
"followers_count": 14,
"following_count": 2,
"statuses_count": 10,
"last_status_at": "2023-06-26",
"noindex": false,
"source": {
"privacy": "public",
"sensitive": false,
"language": null,
"note": "",
"fields": [],
"follow_requests_count": 0
},
"emojis": [],
"roles": [],
"fields": [],
"role": {
"id": "-99",
"name": "",
"permissions": "65536",
"color": "",
"highlighted": false
}
}
```
### 401: Unauthorized
Invalid or missing Authorization header.
```json
{
"error": "The access token is invalid"
}
```
## Delete profile header
```http
DELETE /api/v1/profile/header HTTP/1.1
```
**Returns:** [CredentialAccount]({{< relref "entities/Account#CredentialAccount">}})\
**OAuth**: User token + `write:accounts`\
**Version history:**\
4.2.0 - added
Deletes the header image associated with the user's profile.
#### Request
##### Headers
Authorization
: {{<required>}} Provide this header with `Bearer <user token>` to gain authorized access to this API method.
##### Path parameters
#### Response
##### 200: OK
The header was successfully deleted from the user's profile. If there were no header associated with the profile, the response will still indicate a successful deletion.
```json
{
"id": "110357222516183152",
"username": "rob",
"acct": "rob",
"display_name": "",
"locked": false,
"bot": false,
"discoverable": false,
"group": false,
"created_at": "2023-05-12T00:00:00.000Z",
"note": "",
"url": "http://localhost:3000/@rob",
"uri": "http://localhost:3000/users/rob",
"avatar": "http://localhost:3000/avatars/original/missing.png",
"avatar_static": "http://localhost:3000/avatars/original/missing.png",
"header": "http://localhost:3000/headers/original/missing.png",
"header_static": "http://localhost:3000/headers/original/missing.png",
"followers_count": 14,
"following_count": 2,
"statuses_count": 10,
"last_status_at": "2023-06-26",
"noindex": false,
"source": {
"privacy": "public",
"sensitive": false,
"language": null,
"note": "",
"fields": [],
"follow_requests_count": 0
},
"emojis": [],
"roles": [],
"fields": [],
"role": {
"id": "-99",
"name": "",
"permissions": "65536",
"color": "",
"highlighted": false
}
}
```
### 401: Unauthorized
Invalid or missing Authorization header.
```json
{
"error": "The access token is invalid"
}
```

View File

@ -22,7 +22,7 @@ aliases: [
## About the Web Push API {#about}
Mastodon natively supports the [Web Push API](https://developer.mozilla.org/en-US/docs/Web/API/Push_API). You can utilize the same mechanisms for your native app. It requires running a proxy server that connects to Androids and Apples proprietary notification gateways. However, the proxy server does not have access to the contents of the notifications. For a reference, see [Mozillas web push server](https://github.com/mozilla-services/autopush), or more practically, see:
Mastodon natively supports the [Web Push API](https://developer.mozilla.org/en-US/docs/Web/API/Push_API). You can utilize the same mechanisms for your native app. Mastodon doesn't connect to Androids and Apples proprietary notification gateways directly, so if you wish to use those you can use a proxy server that translates between the WebPush standard and those gateways. This can be implemented in such a way that the proxy server does not have access to the contents of the notifications. For an example, see [Mozillas reference web push server](https://github.com/mozilla-services/autopush), or one of the several relays developed by the Mastodon community specifically for this purpose:
* [toot-relay](https://github.com/DagAgren/toot-relay)
* [PushToFCM](https://github.com/tateisu/PushToFCM)
@ -298,7 +298,7 @@ DELETE /api/v1/push/subscription HTTP/1.1
Removes the current Web Push API subscription.
**Returns:** none\
**Returns:** Empty\
**OAuth:** User token + `push`\
**Version history:**\
2.4.0 - added
@ -334,4 +334,4 @@ Invalid or missing Authorization header.
## See also
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/push/subscriptions_controller.rb" caption="app/controllers/api/v1/push/subscriptions_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/push/subscriptions_controller.rb" caption="app/controllers/api/v1/push/subscriptions_controller.rb" >}}

View File

@ -39,14 +39,14 @@ Authorization
##### Query parameters
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 20 statuses. Max 40 statuses.
@ -243,7 +243,7 @@ ScheduledStatus is not owned by you or does not exist
DELETE /api/v1/scheduled_statuses/:id HTTP/1.1
```
**Returns:** empty object\
**Returns:** Empty\
**OAuth:** User token + `write:statuses`\
**Version history:**\
2.7.0 - added

View File

@ -59,11 +59,11 @@ account_id
exclude_unreviewed
: Boolean. Filter out unreviewed tags? Defaults to false. Use true when trying to find trending tags.
max_id
: String. Return results older than this ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
min_id
: String. Return results immediately newer than this ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return, per type. Defaults to 20 results per category. Max 40 results per category.
@ -188,11 +188,11 @@ resolve
account_id
: String. If provided, will only return statuses authored by this account.
max_id
: String. Return results older than this ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
min_id
: String. Return results immediately newer than this ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return, per type. Defaults to 20 results per category. Max 40 results per category.

View File

@ -1,3 +1,4 @@
---
title: statuses API methods
description: Publish, interact, and view information about statuses.
@ -455,9 +456,10 @@ GET /api/v1/statuses/:id/context HTTP/1.1
View statuses above and below this status in the thread.
**Returns:** [Context]({{< relref "entities/context" >}})\
**OAuth:** Public for public statuses. User token + `read:statuses` for private statuses.\
**OAuth:** Public for public statuses limited to 40 ancestors and 60 descendants with a maximum depth of 20. User token + `read:statuses` for up to 4,096 ancestors, 4,096 descendants, unlimited depth, and private statuses.\
**Version history:**\
0.0.0 - added
4.0.0 - limit unauthenticated requests
#### Request
@ -621,16 +623,13 @@ max_id
since_id
: **Internal parameter.** Use HTTP `Link` header for pagination.
min_id
: **Internal parameter.** Use HTTP `Link` header for pagination.
limit
: Integer. Maximum number of results to return. Defaults to 40 accounts. Max 80 accounts.
#### Response
##### 200: OK
A list of statuses that boosted the status
A list of accounts that boosted the status
```json
[
@ -695,9 +694,6 @@ max_id
since_id
: **Internal parameter.** Use HTTP `Link` header for pagination.
min_id
: **Internal parameter.** Use HTTP `Link` header for pagination.
limit
: Integer. Maximum number of results to return. Defaults to 40 accounts. Max 80 accounts.
@ -1483,6 +1479,9 @@ language
media_ids[]
: Array of String. Include Attachment IDs to be attached as media. If provided, `status` becomes optional, and `poll` cannot be used.
media_attributes[][]
: Array of String. Each array includes id, description, and focus.
poll[options][]
: Array of String. Possible answers to the poll. If provided, `media_ids` cannot be used, and `poll[expires_in]` must be provided.
@ -1856,4 +1855,5 @@ Status does not exist or is private.
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/statuses/reblogs_controller.rb" caption="app/controllers/api/v1/statuses/reblogs_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/statuses/sources_controller.rb" caption="app/controllers/api/v1/statuses/sources_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/statuses/sources_controller.rb" caption="app/controllers/api/v1/statuses/sources_controller.rb" >}}

View File

@ -89,7 +89,7 @@ DELETE /api/v1/suggestions/:account_id HTTP/1.1
Remove an account from follow suggestions.
**Returns:** n/a\
**Returns:** Empty\
**OAuth:** User token + `read`\
**Version history:**\
2.4.3 - added

View File

@ -51,14 +51,14 @@ remote
only_media
: Boolean. Show only statuses with media attached? Defaults to false.
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 20 statuses. Max 40 statuses.
@ -139,14 +139,14 @@ remote
only_media
: Boolean. Return only statuses with media attachments? Defaults to false.
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 20 statuses. Max 40 statuses.
@ -231,7 +231,7 @@ Hashtag does not exist
GET /api/v1/timelines/home HTTP/1.1
```
View statuses from followed users.
View statuses from followed users and hashtags.
**Returns:** Array of [Status]({{<relref "entities/status">}})\
**OAuth:** User + `read:statuses`\
@ -239,6 +239,7 @@ View statuses from followed users.
0.0.0 - added\
2.6.0 - add `min_id`\
3.3.0 - both `min_id` and `max_id` can be used at the same time now
4.0.0 - as users can now follow hashtags, statuses from non-followed users may appear in the timeline
#### Request
@ -249,14 +250,14 @@ Authorization
##### Query parameters
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 20 statuses. Max 40 statuses.
@ -325,14 +326,14 @@ Authorization
##### Query parameters
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 20 statuses. Max 40 statuses.
@ -398,14 +399,14 @@ Authorization
##### Query parameters
max_id
: String. Return results older than ID.
max_id
: String. All results returned will be lesser than this ID. In effect, sets an upper bound on results.
since_id
: String. Return results newer than ID.
: String. All results returned will be greater than this ID. In effect, sets a lower bound on results.
min_id
: String. Return results immediately newer than ID.
: String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward.
limit
: Integer. Maximum number of results to return. Defaults to 20 statuses. Max 40 statuses.
@ -448,4 +449,4 @@ Invalid or missing Authorization header.
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/timelines/public_controller.rb" caption="app/controllers/api/v1/timelines/public_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/timelines/tag_controller.rb" caption="app/controllers/api/v1/timelines/tag_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/api/v1/timelines/tag_controller.rb" caption="app/controllers/api/v1/timelines/tag_controller.rb" >}}

View File

@ -7,13 +7,9 @@ menu:
parent: spec
---
{{< hint style="warning" >}}
Sample payloads will be added at a future date.
{{< /hint >}}
## Status federation {#status}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/lib/activitypub/activity.rb" caption="app/lib/activitypub/activity.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/lib/activitypub/activity.rb" caption="app/lib/activitypub/activity.rb" >}}
### Supported activities for statuses
@ -29,21 +25,21 @@ Like
Announce
: Transformed into a boost on a status
Flag
: Transformed into a report to the moderation team.
Update
: Refresh vote count on polls. As of Mastodon 3.5.0, can be used to edit statuses when the `updated` timestamp is present.
: Refresh vote count on polls. As of Mastodon 3.5.0: edit statuses when the `updated` timestamp is present.
Undo
: Undo a previous Like or Announce.
Flag
: Transformed into a report to the moderation team. See the [Reports](#Flag) extension for more information.
### Payloads
The first-class Object types supported by Mastodon are `Note` and `Question`.
- Notes are transformed into regular statuses.
- Questions are transformed into a poll status.
- Questions are transformed into a poll status. See the [Polls](#Question) extension for more information.
Some other Object types are converted as best as possible:
@ -56,6 +52,64 @@ Some other Object types are converted as best as possible:
The transformer uses `content` if available, or `name` if not, in order to generate status text. The `url` will be appended. The `summary` property will be used as the CW text. The `icon` will be used as a thumbnail.
### HTML sanitization {#sanitization}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/sanitize_ext/sanitize_config.rb" caption="lib/sanitize_ext/sanitize_config.rb" >}}
Mastodon sanitizes incoming HTML in order to not break assumptions for API client developers. Supported elements will be kept as-is, and unsupported elements will be converted or removed. Supported attributes will be kept, and all other attributes will be stripped. The following elements and attributes are supported:
- `<p>`
- `<span>` (`class`)
- `<br>`
- `<a>` (`href`, `rel`, `class`)
- lists will be converted to `<p>`, and list items will be separated with `<br>`
Since Mastodon v4.2, the following elements and attributes are supported:
- `<p>`
- `<span>` (`class`)
- `<br>`
- `<a>` (`href`, `rel`, `class`)
- `<del>`
- `<pre>`
- `<code>`
- `<em>`
- `<strong>`
- `<b>`
- `<i>`
- `<u>`
- `<ul>`
- `<ol>` (`start`, `reversed`)
- `<li>` (`value`)
- `<blockquote>`
- headings will be converted to `<strong>` and then wrapped in `<p>`
The sanitizer will keep classes if they begin with microformats prefixes or are semantic classes:
- h-*
- p-*
- u-*
- dt-*
- e-*
- mention
- hashtag
- ellipsis
- invisible
Links will be kept if the protocol is supported, and converted to text otherwise. The following link protocols are supported:
- http
- https
- dat
- dweb
- ipfs
- ipns
- ssb
- gopher
- xmpp
- magnet
- gemini
### Properties used
content
@ -68,7 +122,7 @@ summary
: Used as CW text
sensitive
: Used to determine whether status media or text should be hidden by default
: Used to determine whether status media or text should be hidden by default. See the [Sensitive content](#sensitive) extension section for more information about `as:sensitive`
inReplyTo
: Used for threading a status as a reply to another status
@ -82,25 +136,17 @@ url
attributedTo
: Used to determine the profile which authored the status
updated
: Used to display the "last edited at" timestamp in the UI to indicate to the user that a status has been edited. Required before an Update activity will be processed. To prevent against race conditions, Mastodon will only process Update payloads with an `updated` timestamp greater than the currently known last `updated` time.
to/cc
: Used to determine audience and visibility of a status.
- Public statuses have the `as:Public` magic collection in `to`
- Unlisted statuses have the `as:Public` magic collection in `cc`
- Followers-only statuses have an actor's follower collection in `to` or `cc`, but do not include the `as:Public` magic collection
- Private statuses have actors in `to` or `cc`, at least one of which is not `Mention`ed in `tag`
- Direct statuses have actors in `to` or `cc`, all of which are `Mention`ed in `tag`
: Used to determine audience and visibility of a status, in combination with mentions. See [Mentions for adddressing and notifications](#Mention)
tag
: Used to mark up mentions and hashtags.
tag[].type
: Either `Mention` or `Hashtag` is currently supported
: Either `Mention`, `Hashtag`, or `Emoji` is currently supported. See the [Hashtag](#Hashtag) and [Custom emoji](#Emoji) extension sections for more information
tag[].name
: The plain-text Webfinger address of a profile Mention (`@user` or `@user@domain`), or the plain-text Hashtag (`#tag`)
: The plain-text Webfinger address of a profile Mention (`@user` or `@user@domain`), or the plain-text Hashtag (`#tag`), or the custom Emoji shortcode (`:thounking:`)
tag[].href
: The URL of the actor or tag
@ -156,24 +202,24 @@ Accept/Reject
Add/Remove
: Manage pinned posts and featured collections.
Block
: Signal to a remote server that they should hide your profile from that user. Not guaranteed.
Flag
: Report user
Update
: Refresh account details
Move
: Migrate followers from one account to another. Requires alsoKnownAs to be set in both directions.
Delete
: Remove an account from the database, as well as all of their statuses.
Undo
: Undo a previous Follow, Accept Follow, or Block.
Block
: Signal to a remote server that they should hide your profile from that user. Not guaranteed. See [Remote blocking](#Block) for more information.
Flag
: Report a user to their moderation team. See the [Reports](#Flag) extension for more information.
Move
: Migrate followers from one account to another. Requires `alsoKnownAs` to be set on the new account pointing to the old account.
### Properties used
preferredUsername
@ -218,82 +264,241 @@ alsoKnownAs
published
: When the profile was created.
## JSON-LD Contexts and Extensions {#contexts}
## HTML sanitization {#sanitization}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/sanitize_ext/sanitize_config.rb" caption="lib/sanitize_ext/sanitize_config.rb" >}}
Mastodon sanitizes incoming HTML in order to not break assumptions for API client developers. Supported elements include `<p>`, `<span>`, `<br>`, and `<a>`. Unsupported elements will be converted to `<p>`.The sanitizer will keep classes if they begin with microformats prefixes or are semantic classes:
- h-*
- p-*
- u-*
- dt-*
- e-*
- mention
- hashtag
- ellipsis
- invisible
## JSON-LD Namespacing {#namespaces}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/lib/activitypub/adapter.rb" caption="app/lib/activitypub/adapter.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/lib/activitypub/adapter.rb" caption="app/lib/activitypub/adapter.rb" >}}
### Mastodon extensions (`toot:`) {#toot}
Base URI: `http://joinmastodon.org/ns#`
Contains definitions for Mastodon features.
- toot:Emoji
- toot:IdentityProof
- toot:blurhash
- toot:focalPoint
- toot:featured
- toot:featuredTags
- toot:discoverable
- toot:suspended
- toot:votersCount
- toot:Emoji (`http://joinmastodon.org/ns#Emoji`)
- toot:IdentityProof (`http://joinmastodon.org/ns#IdentityProof`)
- toot:blurhash (`http://joinmastodon.org/ns#blurhash`)
- toot:focalPoint (`http://joinmastodon.org/ns#focalPoint`)
- toot:featured (`http://joinmastodon.org/ns#featured`)
- toot:featuredTags (`http://joinmastodon.org/ns#featuredTags`)
- toot:discoverable (`http://joinmastodon.org/ns#discoverable`)
- toot:suspended (`http://joinmastodon.org/ns#suspended`)
- toot:votersCount (`http://joinmastodon.org/ns#votersCount`)
### ActivityStreams extensions (`as:`) {#as}
Base URI: `https://www.w3.org/ns/activitystreams#`
Contains ActivityStreams extended properties that have been proposed but not officially adopted yet.
- as:Hashtag
- as:alsoKnownAs
- as:manuallyApprovesFollowers
- as:movedTo
- as:sensitive
- as:Hashtag (`https://www.w3.org/ns/activitystreams#Hashtag`)
- as:manuallyApprovesFollowers (`https://www.w3.org/ns/activitystreams#manuallyApprovesFollowers`)
- as:movedTo (`https://www.w3.org/ns/activitystreams#movedTo`)
- as:sensitive (`https://www.w3.org/ns/activitystreams#sensitive`)
### W3ID Security Vocabulary (`sec:`) {#sec}
Contains properties used for HTTPS Signatures and Linked Data Signatures. Also used for identity proofs. See [Security]({{< relref "spec/security" >}}) for more information.
- sec:publicKey
- sec:publicKeyPem
- sec:owner
- sec:signature
- sec:signatureValue
#### W3ID Identity
Contains a collection of terms from various namespaces, used for Linked Data Signatures.
- dc:creator
- dc:created
- sec:signature
- sec:signatureValue
### schema.org extensions (`schema:`) {#schema}
### Schema.org extensions (`schema:`) {#schema}
Contains properties used for profile metadata.
- schema:PropertyValue
- schema:value
Base URI: `http://schema.org#` (incorrect; should be `https://schema.org/`)
## Extensions
- [schema:PropertyValue (`http://schema.org#PropertyValue`, should be `https://schema.org/PropertyValue`)](https://schema.org/PropertyValue)
- [schema:value (`http://schema.org#value`, should be `https://schema.org/value`)](https://schema.org/value)
### W3ID Security Vocabulary (`sec:`) {#sec}
Context: [`https://w3id.org/security/v1`](https://w3id.org/security/v1)
Used for HTTPS Signatures. Also used for identity proofs. See [Security]({{< relref "spec/security" >}}) for more information.
- [sec:publicKey (`https://w3id.org/security#publicKey`)](https://w3id.org/security#publicKey)
- [sec:publicKeyPem (`https://w3id.org/security#publicKeyPem`)](https://w3id.org/security#publicKeyPem)
- [sec:owner (`https://w3id.org/security#owner`)](https://w3id.org/security#owner)
- [sec:signature (`https://w3id.org/security#signature`)](https://w3id.org/security#signature)
- [sec:signatureValue (`https://w3id.org/security#signatureValue`)](https://w3id.org/security#signatureValue)
#### W3ID Identity
Context: [`https://w3id.org/identity/v1`](https://w3id.org/identity/v1) (offline)
Used for Linked Data Signatures. See [Security > Linked Data Signatures]({{< relref "spec/security#ld" >}}) for more information.
- [dc:creator (`http://purl.org/dc/terms/creator`)](http://purl.org/dc/terms/creator)
- [dc:created (`http://purl.org/dc/terms/created`)](http://purl.org/dc/terms/created)
- [sec:signature (`https://w3id.org/security#signature`)](https://w3id.org/security#signature)
- [sec:signatureValue (`https://w3id.org/security#signatureValue`)](https://w3id.org/security#signatureValue)
## Extensions defined using ActivityStreams vocabulary
While the Activity Vocabulary defines a wide range of types and terms, ActivityPub only defines side effects for a subset of them. The following activity types have the following side effects when received in a Mastodon inbox.
### Remote blocking (`Block`) {#Block}
ActivityPub defines the `Block` activity for client-to-server (C2S) use-cases, but not for server-to-server (S2S) -- it recommends that servers SHOULD NOT deliver Block activities to their `object`. However, Mastodon will send this activity when a local user blocks a remote user. When Mastodon receives a `Block` activity where the `object` is an actor on the local domain, it will interpret this as a signal to hide the actor's profile and posts from the local user, as well as disallowing mentions of that actor by that local user.
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.example/bd06bb61-01e0-447a-9dc8-95915db9aec8",
"type": "Block",
"actor": "https://mastodon.example/users/alice",
"object": "https://example.com/~mallory",
"to": "https://example.com/~mallory"
}
```
### Reporting profiles and posts (`Flag`) {#Flag}
To report profiles and/or posts on remote servers, Mastodon will send a `Flag` activity from the instance actor. The `object` of this activity contains the user being reported, as well as any posts attached to the report. If a comment is attached to the report, it will be used as the `content` of the activity.
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.example/ccb4f39a-506a-490e-9a8c-71831c7713a4",
"type": "Flag",
"actor": "https://mastodon.example/actor",
"content": "Please take a look at this user and their posts",
"object": [
"https://example.com/users/1",
"https://example.com/posts/380590",
"https://example.com/posts/380591"
],
"to": "https://example.com/users/1"
}
```
### Account migration (`Move`) {#Move}
Mastodon uses the Move activity to signal that an account has migrated to a different account. For the migration to be considered valid, Mastodon checks that the new account has defined an alias pointing to the old account (via the `alsoKnownAs` property).
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.example/users/alice#moves/1",
"actor": "https://mastodon.example/users/alice",
"type": "Move",
"object": "https://mastodon.example/users/alice",
"target": "https://alice.com/users/109835986274379",
"to": "https://mastodon.example/users/alice/followers"
}
```
### Polls {#Question}
{{< caption-link url="https://www.w3.org/TR/activitystreams-vocabulary/#questions" caption="Activity Vocabulary §5.4 - Representing Questions" >}}
The ActivityStreams Vocabulary specification describes loosely (non-normatively) how a question might be represented. Mastodon's implementation of polls is somewhat inspired by this section. The following implementation details can be observed:
- `Question` is used as an `Object` type instead of as an `IntransitiveActivity`; rather than being sent directly, it is wrapped in a `Create` just like any other status.
- Poll options are serialized using `oneOf` or `anyOf` as an array.
- Each item in this array has no `id`, has a `type` of `Note`, and has a `name` representing the text of the poll option.
- Each item in this array also has a `replies` property, representing the responses to this particular poll option. This node has no `id`, has a `type` of `Collection`, and has a `totalItems` property representing the total number of votes received for this option.
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"votersCount": "http://joinmastodon.org/ns#votersCount"
}
],
"id": "https://mastodon.example/users/alice/statuses/1009947848598745",
"type": "Question",
"content": "What should I eat for breakfast today?",
"published": "2023-03-05T07:40:13Z",
"endTime": "2023-03-06T07:40:13Z",
"votersCount": 7,
"anyOf": [
{
"type": "Note",
"name": "apple",
"replies": {
"type": "Collection",
"totalItems": 3
}
},
{
"type": "Note",
"name": "orange",
"replies": {
"type": "Collection",
"totalItems": 7
}
},
{
"type": "Note",
"name": "banana",
"replies": {
"type": "Collection",
"totalItems": 6
}
}
]
}
```
- Poll votes are serialized as `Create` activities, where the `object` is a `Note` with a `name` that exactly matches the `name` of the poll option. The `Note.inReplyTo` points to the URI of the `Question` object.
- For multiple-choice polls, multiple activities may be sent. Votes will be counted if you have not previously voted for that option.
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.example/users/bob#votes/827163/activity",
"to": "https://mastodon.example/users/alice",
"actor": "https://mastodon.example/users/bob",
"type": "Create",
"object": {
"id": "https://mastodon.example/users/bob#votes/827163",
"type": "Note",
"name": "orange",
"attributedTo": "https://mastodon.example/users/bob",
"to": "https://mastodon.example/users/alice",
"inReplyTo": "https://mastodon.example/users/alice/statuses/1009947848598745"
}
}
```
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://mastodon.example/users/bob#votes/827164/activity",
"to": "https://mastodon.example/users/alice",
"actor": "https://mastodon.example/users/bob",
"type": "Create",
"object": {
"id": "https://mastodon.example/users/bob#votes/827164",
"type": "Note",
"name": "banana",
"attributedTo": "https://mastodon.example/users/bob",
"to": "https://mastodon.example/users/alice",
"inReplyTo": "https://mastodon.example/users/alice/statuses/1009947848598745"
}
}
```
### Mentions for addressing and notifications {#Mention}
{{< caption-link url="https://www.w3.org/TR/activitystreams-vocabulary/#microsyntaxes" caption="Activity Vocabulary §5.6 - Mentions, Tags, and Other Common Social Microsyntaxes" >}}
In the ActivityStreams Vocabulary, `Mention` is a subtype of `Link` that is intended to represent the microsyntax of @mentions. The `tag` property is intended to add references to other Objects or Links. For Link tags, the `name` of the Link should be a substring of the natural language properties (`name`, `summary`, `content`) on that object. Wherever such a substring is found, it can be transformed into a hyperlink reference to the `href`.
However, Mastodon also uses `Mention` tags for addressing in some cases. Based on the presence or exclusion of Mention tags, and compared to the explicitly declared audiences in `to` and `cc`, Mastodon will calculate a visibility level for the post. Additionally, Mastodon requires Mention tags in order to generate a notification. (The mentioned actor must still be included within `to` or `cc` explicitly in order to receive the post.)
- `public`: Public statuses have the `as:Public` magic collection in `to`
- `unlisted`: Unlisted statuses have the `as:Public` magic collection in `cc`
- `private`: Followers-only statuses have an actor's follower collection in `to` or `cc`, but do not include the `as:Public` magic collection
- `limited`: Limited-audience statuses have actors in `to` or `cc`, at least one of which is not `Mention`ed in `tag`
- `direct`: Mentions-only statuses have actors in `to` or `cc`, all of which are `Mention`ed in `tag`
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/lib/activitypub/activity/create.rb" caption="app/lib/activitypub/activity/create.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/lib/activitypub/parser/status_parser.rb" caption="app/lib/activitypub/parser/status_parser.rb" >}}
## Extensions not defined by ActivityStreams
The following features are defined using properties and types that are not defined by ActivityStreams.
### Public key {#publicKey}
Public keys are used for HTTPS Signatures and Linked Data Signatures. This is implemented using an extra property `publicKey` on actor objects. See [Security]({{< relref "spec/security" >}}) for more information. Example:
Public keys are used for HTTP Signatures and Linked Data Signatures. This is implemented using an extra property `publicKey` on actor objects. See [Security]({{< relref "spec/security" >}}) for more information.
```json
{
@ -313,16 +518,15 @@ Public keys are used for HTTPS Signatures and Linked Data Signatures. This is im
### Featured collection {#featured}
What is known in Mastodon as “pinned statuses”, or statuses that are always featured at the top of peoples profiles, is implemented using an extra property `featured` on the actor object that points to a `Collection` of objects. Example:
What is known in Mastodon as “pinned statuses”, or statuses that are always featured at the top of peoples profiles, is implemented using an extra property `featured` on the actor object that points to a `Collection` of objects.
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"toot": "http://joinmastodon.org/ns#",
"featured": {
"@id": "toot:featured",
"@id": "http://joinmastodon.org/ns#featured",
"@type": "@id"
}
}
@ -343,9 +547,8 @@ Mastodon allows users to feature specific hashtags on their profile for easy bro
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"toot": "http://joinmastodon.org/ns#",
"featuredTags": {
"@id": "toot:featuredTags",
"@id": "http://joinmastodon.org/ns#featuredTags",
"@type": "@id"
}
}
@ -357,113 +560,20 @@ Mastodon allows users to feature specific hashtags on their profile for easy bro
}
```
### Custom emojis {#emoji}
Mastodon supports arbitrary emojis, that is, small images uploaded by admins and invokable via shortcodes. For this, an `Emoji` type is used. These emojis are listed in the `tag` property just like `Mention` and `Hashtag` objects, since they are entities that affect how the text is rendered. Example:
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"toot": "http://joinmastodon.org/ns#",
"Emoji": "toot:Emoji"
}
],
"id": "https://example.com/@alice/hello-world",
"type": "Note",
"content": "Hello world :kappa:",
"tag": [
{
"id": "https://example.com/emoji/123",
"type": "Emoji",
"name": ":kappa:",
"icon": {
"type": "Image",
"mediaType": "image/png",
"url": "https://example.com/files/kappa.png"
}
}
]
}
```
### Focal points {#focalPoint}
Mastodon supports setting a focal point on uploaded images, so that wherever that image is displayed, the focal point stays in view. This is implemented using an extra property `focalPoint` on `Image` objects. The property is an array of two floating points between -1.0 and 1.0, with 0,0 being the center of the image, the first value being x (-1.0 is the left edge, +1.0 is the right edge) and the second value being y (-1.0 is the bottom edge, +1.0 is the top edge). See [API Guidelines > Focal points]({{< relref "api/guidelines#focal-points" >}}) for more information. Example:
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"toot": "http://joinmastodon.org/ns#",
"focalPoint": {
"@container": "@list",
"@id": "toot:focalPoint"
}
}
],
"id": "https://example.com/@alice/hello-world",
"type": "Note",
"content": "A picture attached!",
"attachment": [
{
"type": "Image",
"mediaType": "image/png",
"url": "https://example.com/files/cats.png",
"focalPoint": [
-0.55,
0.43
]
}
]
}
```
{{< figure src="assets/focal-points.jpg" caption="A demonstration of various focal points and their coordinates." >}}
The focal point of (-0.55, 0.43) in the example above corresponds to a point 55% to the left of center and 43% above center. This focal point should remain visible within the cropped thumbnail, if any cropping is done.
### Blurhash {#blurhash}
Mastodon generates colorful preview thumbnails for attachments. This is implemented using an extra property `blurhash` on `Image` objects. The property is a string generated by the [BlurHash algorithm](https://blurha.sh). Example:
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"toot": "http://joinmastodon.org/ns#",
"blurhash": "toot:blurhash"
}
],
"id": "https://example.com/@alice/hello-world",
"type": "Note",
"content": "A picture attached!",
"attachment": [
{
"type": "Image",
"mediaType": "image/png",
"url": "https://example.com/files/cats.png",
"blurhash": "UBL_:rOpGG-oBUNG,qRj2so|=eE1w^n4S5NH"
}
]
}
```
### Profile metadata {#PropertyValue}
Mastodon supports arbitrary profile fields containing name-value pairs. This is implemented using the `attachment` property on actor objects, with objects in the array having a type of `PropertyValue` and a `value` property, both from the schema.org namespace. Example:
Mastodon supports arbitrary profile fields containing name-value pairs. This is implemented using the `attachment` property on actor objects, with objects in the array having a type of `PropertyValue` and a `value` property, both from the schema.org namespace.
{{<hint style="warning">}}
As noted above while listing the [schema.org @context extensions](#schema), Mastodon currently incorrectly expects and maps the term `schema` to the base URI `http://schema.org#` instead of to the base URI `https://schema.org/`. Therefore, JSON-LD processors who use the correct context definition will fail to process profile fields correctly.
{{</hint>}}
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
"value": "schema:value"
}
@ -491,7 +601,7 @@ Mastodon supports arbitrary profile fields containing name-value pairs. This is
This property is currently unused/deprecated due to the removal of Keybase support in Mastodon 3.5: <https://github.com/mastodon/mastodon/pull/17045>
{{</hint>}}
Mastodon supports integration with identity providers to prove that a profile is linked to a certain identity. This is implemented using the `attachment` property on actor objects, with objects in the array having a type of `IdentityProof` from the Mastodon namespace. The object also includes `signatureAlgorithm` and `signatureValue` from the W3ID Security Vocabulary namespace. Example:
Mastodon supports integration with identity providers to prove that a profile is linked to a certain identity. This is implemented using the `attachment` property on actor objects, with objects in the array having a type of `IdentityProof` from the Mastodon namespace. The object also includes `signatureAlgorithm` and `signatureValue` from the W3ID Security Vocabulary namespace.
```json
{
@ -499,8 +609,7 @@ Mastodon supports integration with identity providers to prove that a profile is
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"toot": "http://joinmastodon.org/ns#",
"IdentityProof": "toot:IdentityProof"
"IdentityProof": "http://joinmastodon.org/ns#IdentityProof"
}
],
"id": "https://mastodon.social/users/Gargron",
@ -518,15 +627,14 @@ Mastodon supports integration with identity providers to prove that a profile is
### Discoverability flag {#discoverable}
Mastodon allows users to opt-in or opt-out of discoverability features like the profile directory. This flag may also be used as an indicator of the user's preferences toward being included in external discovery services, such as search engines or other indexing tools. If you are implementing such a tool, it is recommended that you respect this property if it is present. This is implemented using an extra property `discoverable` on objects. Example:
Mastodon allows users to opt-in or opt-out of discoverability features like the profile directory. This flag may also be used as an indicator of the user's preferences toward being included in external discovery services, such as search engines or other indexing tools. If you are implementing such a tool, it is recommended that you respect this property if it is present. This is implemented using an extra property `discoverable` on objects.
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"toot": "http://joinmastodon.org/ns#",
"discoverable": "toot:discoverable"
"discoverable": "http://joinmastodon.org/ns#discoverable"
}
],
"id": "https://mastodon.social/users/Gargron",
@ -537,15 +645,14 @@ Mastodon allows users to opt-in or opt-out of discoverability features like the
### Suspended flag {#suspended}
Mastodon reports whether a user was locally suspended, for better handling of these accounts. Suspended accounts in Mastodon return empty data. If a remote account is marked as suspended, it cannot be unsuspended locally. Suspended accounts can be targeted by activities such as Update, Undo, Reject, and Delete. This functionality is implemented using an extra property `suspended` on objects. Example:
Mastodon reports whether a user was locally suspended, for better handling of these accounts. Suspended accounts in Mastodon return empty data. If a remote account is marked as suspended, it cannot be unsuspended locally. Suspended accounts can be targeted by activities such as Update, Undo, Reject, and Delete. This functionality is implemented using an extra property `suspended` on objects.
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"toot": "http://joinmastodon.org/ns#",
"suspended": "toot:suspended"
"suspended": "http://joinmastodon.org/ns#suspended"
}
],
"id": "https://example.com/@eve",
@ -554,6 +661,133 @@ Mastodon reports whether a user was locally suspended, for better handling of th
}
```
### Hashtags {#Hashtag}
Similar to the `Mention` subtype of Link already defined in ActivityStreams, Mastodon will use `Hashtag` as a subtype of Link in order to surface posts referencing some common topic identified by a string key. The Hashtag has a `name` containing the #hashtag microsyntax -- a `#` followed by a string sequence representing a topic. This is similar to the @mention microsyntax, where an `@` is followed by some string sequence representing a resource (where in Mastodon's case, this resource is expected to be an account). Mastodon will also normalize hashtags to be case-insensitive lowercase strings, performing ASCII folding and removing invalid characters.
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/lib/hashtag_normalizer.rb" caption="app/lib/hashtag_normalizer.rb" >}}
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"Hashtag": "https://www.w3.org/ns/activitystreams#Hashtag"
}
],
"id": "https://example.com/some-post",
"type": "Note",
"attributedTo": "https://example.com",
"content": "I love #cats",
"tag": [
{
"type": "Hashtag",
"name": "#cats",
"href": "https://example.com/tagged/cats"
}
]
}
```
### Custom emojis {#Emoji}
Mastodon supports arbitrary emojis by including a `tag` of the `Emoji` type. Handling of custom emojis is similar to handling of mentions and hashtags, where the `name` of the tagged entity is found as a substring of the natural language properties (`name`, `summary`, `content`) and then linked to the local representation of some resource or topic. In the case of emoji shortcodes, the `name` is replaced by the HTML for an inline image represented by the `icon` property (where `icon.url` links to the image resource).
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"Emoji": "http://joinmastodon.org/ns#Emoji",
}
],
"id": "https://example.com/@alice/hello-world",
"type": "Note",
"content": "Hello world :kappa:",
"tag": [
{
"id": "https://example.com/emoji/123",
"type": "Emoji",
"name": ":kappa:",
"icon": {
"type": "Image",
"mediaType": "image/png",
"url": "https://example.com/files/kappa.png"
}
}
]
}
```
### Focal points {#focalPoint}
Mastodon supports setting a focal point on uploaded images, so that wherever that image is displayed, the focal point stays in view. This is implemented using an extra property `focalPoint` on `Image` objects. The property is an array of two floating points between -1.0 and 1.0, with 0,0 being the center of the image, the first value being x (-1.0 is the left edge, +1.0 is the right edge) and the second value being y (-1.0 is the bottom edge, +1.0 is the top edge). See [API Guidelines > Focal points]({{< relref "api/guidelines#focal-points" >}}) for more information.
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"focalPoint": {
"@container": "@list",
"@id": "http://joinmastodon.org/ns#focalPoint"
}
}
],
"id": "https://example.com/@alice/hello-world",
"type": "Note",
"content": "A picture attached!",
"attachment": [
{
"type": "Image",
"mediaType": "image/png",
"url": "https://example.com/files/cats.png",
"focalPoint": [
-0.55,
0.43
]
}
]
}
```
{{< figure src="/assets/focal-points.jpg" caption="A demonstration of various focal points and their coordinates." >}}
The focal point of (-0.55, 0.43) in the example above corresponds to a point 55% to the left of center and 43% above center. This focal point should remain visible within the cropped thumbnail, if any cropping is done.
### Blurhash {#blurhash}
Mastodon generates colorful preview thumbnails for attachments. This is implemented using an extra property `blurhash` on `Image` objects. The property is a string generated by the [BlurHash algorithm](https://blurha.sh).
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"blurhash": "http://joinmastodon.org/ns#blurhash"
}
],
"id": "https://example.com/@alice/hello-world",
"type": "Note",
"content": "A picture attached!",
"attachment": [
{
"type": "Image",
"mediaType": "image/png",
"url": "https://example.com/files/cats.png",
"blurhash": "UBL_:rOpGG-oBUNG,qRj2so|=eE1w^n4S5NH"
}
]
}
```
### Sensitive content {#sensitive}
Mastodon uses the `as:sensitive` extension property to mark certain posts as sensitive. When a post is marked as sensitive, any media attached to it will be hidden by default, and if a `summary` is present, the status `content` will be collapsed behind this summary. In Mastodon, this is known as a **content warning**.
## Other functionality
### Secure mode {#secure-mode}
@ -596,4 +830,4 @@ Signature: ... # a signature from an account on mastodon.social
"https://mastodon.social/users/Gargron"
]
}
```
```

View File

@ -17,7 +17,7 @@ To obtain an OAuth token for a Mastodon website, make sure that you allow your u
The following descriptions are taken from the [Doorkeeper documentation](https://github.com/doorkeeper-gem/doorkeeper/wiki/API-endpoint-descriptions-and-examples). Mastodon uses Doorkeeper to implement OAuth 2. For more information on how to use these endpoints, see the [API documentation for OAuth.]({{< relref "methods/oauth" >}})
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/config/initializers/doorkeeper.rb" caption="Doorkeeper config initializer" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/config/initializers/doorkeeper.rb" caption="Doorkeeper config initializer" >}}
### Authorization endpoint (RFC 6749 Section 3.1) {#authorization}

View File

@ -9,21 +9,21 @@ menu:
## HTTP Signatures {#http}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/lib/request.rb" caption="app/lib/request.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/lib/request.rb" caption="app/lib/request.rb" >}}
[HTTP Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures) is a specification for signing HTTP messages by using a `Signature:` header with your HTTP request. Mastodon requires the use of HTTP Signatures in order to validate that any activity received was authored by the actor generating it. When secure mode is enabled, all GET requests require HTTP signatures as well.
For any HTTP request incoming to Mastodon, the Signature header should be attached:
```http
Signature: keyId="https://my-example.com/actor#main-key",headers="(request-target) host date",signature="Y2FiYW...IxNGRiZDk4ZA=="
Signature: keyId="https://my.example.com/actor#main-key",headers="(request-target) host date",signature="Y2FiYW...IxNGRiZDk4ZA=="
```
The three parts of the `Signature:` header can be broken down like so:
```http
Signature:
keyId="https://my-example.com/actor#main-key",
keyId="https://my.example.com/actor#main-key",
headers="(request-target) host date",
signature="Y2FiYW...IxNGRiZDk4ZA=="
```
@ -32,8 +32,8 @@ The `keyId` should correspond to the actor and the key being used to generate th
```json
"publicKey": {
"id": "https://my-example.com/actor#main-key",
"owner": "https://my-example.com/actor",
"id": "https://my.example.com/actor#main-key",
"owner": "https://my.example.com/actor",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvXc4vkECU2/CeuSo1wtn\nFoim94Ne1jBMYxTZ9wm2YTdJq1oiZKif06I2fOqDzY/4q/S9uccrE9Bkajv1dnkO\nVm31QjWlhVpSKynVxEWjVBO5Ienue8gND0xvHIuXf87o61poqjEoepvsQFElA5ym\novljWGSA/jpj7ozygUZhCXtaS2W5AD5tnBQUpcO0lhItYPYTjnmzcc4y2NbJV8hz\n2s2G8qKv8fyimE23gY1XrPJg+cRF+g4PqFXujjlJ7MihD9oqtLGxbu7o1cifTn3x\nBfIdPythWu5b4cujNsB3m3awJjVmx+MHQ9SugkSIYXV0Ina77cTNS0M2PYiH1PFR\nTwIDAQAB\n-----END PUBLIC KEY-----\n"
},
```
@ -68,38 +68,38 @@ GET /users/username/inbox HTTP/1.1
Host: mastodon.example
Date: 18 Dec 2019 10:08:46 GMT
Accept: application/ld+json; profile="http://www.w3.org/ns/activitystreams"
Signature: keyId="https://my-example.com/actor#main-key",headers="(request-target) host date",signature="Y2FiYW...IxNGRiZDk4ZA=="
Signature: keyId="https://my.example.com/actor#main-key",headers="(request-target) host date",signature="Y2FiYW...IxNGRiZDk4ZA=="
```
This request is functionally equivalent to saying that `https://my-example.com/actor` is requesting `https://mastodon.example/users/username/inbox` and is proving that they sent this request by signing `(request-target)`, `Host:`, and `Date:` with their private key linked at `keyId`, resulting in the provided `signature`.
This request is functionally equivalent to saying that `https://my.example.com/actor` is requesting `https://mastodon.example/users/username/inbox` and is proving that they sent this request by signing `(request-target)`, `Host:`, and `Date:` with their private key linked at `keyId`, resulting in the provided `signature`.
#### Signing POST requests and the Digest header {#digest}
When making a POST request to Mastodon, you must calculate the RSA-SHA256 digest hash of your request's body and include this hash within the `Digest:` header. The `Digest:` header must also be included within the `headers` parameter of the `Signature:` header. For example:
When making a POST request to Mastodon, you must calculate the RSA-SHA256 digest hash of your request's body and include this hash (in base64 encoding) within the `Digest:` header. The `Digest:` header must also be included within the `headers` parameter of the `Signature:` header. For example:
```http
POST /users/username/inbox HTTP/1.1
HOST: mastodon.example
Date: 18 Dec 2019 10:08:46 GMT
Digest: e37e179c75071a291f90a5fd4f848da87b491f1282f7bb8509ef2115b81ee0f4
Signature: keyId="https://my-example.com/actor#main-key",headers="(request-target) host date digest",signature="Y2FiYW...IxNGRiZDk4ZA=="
Digest: sha-256=hcK0GZB1BM4R0eenYrj9clYBuyXs/lemt5iWRYmIX0A=
Signature: keyId="https://my.example.com/actor#main-key",headers="(request-target) host date digest",signature="Y2FiYW...IxNGRiZDk4ZA=="
Content-Type: application/ld+json; profile="http://www.w3.org/ns/activitystreams"
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.com/actor",
"actor": "https://my.example.com/actor",
"type": "Create",
"object": {
"type": "Note",
"content": "Hello!"
}
},
"to": "https://mastodon.example/users/username"
}
```
### Verifying HTTP signatures {#http-verify}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/controllers/concerns/signature_verification.rb" caption="app/controllers/concerns/signature_verification.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb" caption="app/controllers/concerns/signature_verification.rb" >}}
Consider the following request:
@ -108,12 +108,12 @@ POST /users/username/inbox HTTP/1.1
Host: mastodon.example
Date: 18 Dec 2019 10:08:46 GMT
Digest: e37e179c75071a291f90a5fd4f848da87b491f1282f7bb8509ef2115b81ee0f4
Signature: keyId="https://my-example.com/actor#main-key",headers="(request-target) host date digest",signature="Y2FiYW...IxNGRiZDk4ZA=="
Signature: keyId="https://my.example.com/actor#main-key",headers="(request-target) host date digest",signature="Y2FiYW...IxNGRiZDk4ZA=="
Content-Type: application/ld+json; profile="http://www.w3.org/ns/activitystreams"
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.com/actor",
"actor": "https://my.example.com/actor",
"type": "Create",
"object": {
"type": "Note",
@ -133,7 +133,7 @@ Mastodon verifies the signature using the following algorithm:
## Linked Data Signatures {#ld}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/app/lib/activitypub/linked_data_signature.rb" caption="app/lib/activitypub/linked_data_signature.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/lib/activitypub/linked_data_signature.rb" caption="app/lib/activitypub/linked_data_signature.rb" >}}
{{< hint style="warning" >}}
Mastodon's current implementation of LD Signatures is outdated due to a change in the JSON-LD `@context` between the drafting stage and finalization stage of the specification. Mastodon expects a `type` of `RsaSignature2017` while later drafts instead define `RsaSignature2018` via the namespace `https://w3id.org/security/v2`. Furthermore, the LD Signatures specification as a whole has been superseded by the [Verifiable Credential Data Integrity 1.0](https://w3c.github.io/vc-data-integrity/) specification, which is largely incompatible with the earlier LD Signature spec. For this reason, it is not advised to implement support for LD Signatures.

View File

@ -92,7 +92,7 @@ If you and the blocked user are on the same server, the blocked user will not be
### Hiding an entire server {#block-domain}
![]({{relURL "assets/block-domain.png" }})
{{< figure src="assets/block-domain.png" caption="Sample of blocking an entire domain." >}}
If you block an entire server:

View File

@ -13,7 +13,7 @@ menu:
At any time you want, you can go to Settings &gt; Export and download a CSV file for your current followed accounts, your currently created lists, your currently blocked accounts, your currently muted accounts, and your currently blocked domains. Your following, blocking, muting, and domain-blocking lists can be imported at Settings &gt; Import, where they can either be merged or overwritten.
Requesting an archive of your posts and media can be done once every 7 days, and can be downloaded in ActivityPub JSON format. Mastodon currently does not support importing posts or media due to technical limitations, but your archive can be viewed by any software that understands how to parse ActivityPub documents.
Requesting an archive of your posts and media can be done once every 7 days, and can be downloaded in Activity Streams 2.0 JSON format. Mastodon currently does not support importing posts or media due to technical limitations, but your archive can be viewed by any software that understands how to parse Activity Streams 2.0 documents.
## Redirecting or moving your profile {#migration}

View File

@ -44,7 +44,7 @@ When unread notifications are present, a checkmark will appear in the column hea
## Following profiles {#follow}
![]({{ relUrl "/assets/profile.jpg" }})
{{< figure src="assets/profile.jpg" caption="Overview of a profile." >}}
As long as you encounter a person within your apps user interface, e.g. the web interface on your home server, or your mobile app, you can just click “follow” and you wont notice a difference if that person is on your server or not.
@ -54,7 +54,7 @@ If you are visiting a public page on another Mastodon site, see [Using Mastodon
## Enabling notifications {#bell}
![]({{ relUrl "/assets/bell.jpg" }})
{{< figure src="assets/bell.jpg" caption="An example of a profile that you are following." >}}
If you are following someone, you also have the option to receive a notification every time they post. To opt into this functionality, click the bell icon.
@ -90,7 +90,8 @@ In Mastodon, direct messages are just posts that have the "direct" visibility se
Lists are subsets of your home timeline. You can create a list, give it a name, and add users that you follow to that list.
![]({{ relUrl "/assets/lists.jpg" }})
{{< figure src="assets/lists.jpg" caption="A list of lists" >}}
Opening a list will load that list's timeline. List timelines contain only posts by members of that list, as well as replies to you or to other members of the list. This can be changed to show replies to all people you follow, or to no one.

View File

@ -47,10 +47,11 @@ You can attach either files or a poll to your status.
Click the paper clip to attach a file to your post. You can attach the following:
* **Images** (PNG, JPG, GIF) **up to 8MB**. Images will be downscaled to 1.6 megapixels (enough for a 1280x1280 image). Up to 4 images can be attached.
* **Animated GIFs** are converted to soundless MP4s like on Imgur/Gfycat (**GIFV**). You can also upload soundless MP4 and WebM, which will be handled the same way.
* **Videos** (MP4, M4V, MOV, WebM) **up to 40MB**. Video will be transcoded to H.264 MP4 with a maximum bitrate of 1300kbps and framerate of 60fps.
* **Audio** (MP3, OGG, WAV, FLAC, OPUS, AAC, M4A, 3GP) **up to 40MB**. Audio will be transcoded to MP3 using V2 VBR (roughly 192kbps).
* **Images** (PNG, JPG, HEIF, WEBP) **up to 16MB**. Images will be downscaled to 8.3 megapixels (enough for a 3840x2160 image). Up to 4 images can be attached, per post.
* **Animated GIFs** (GIFV) **up to 16MB** are converted to soundless MP4s. GIF dimensions must be less than 1MP (1280x720). You can also upload soundless MP4 and WebM files, which will be looped in clients the same way as an animated GIF. Only one animated GIF can be attached, per post.
* Static GIF files have the same limits applied to them as animated GIF files. If you are having issues uploading these images, you will need to convert it to another supported image format.
* **Videos** (MP4, M4V, MOV, WebM) **up to 99MB**. Video will be transcoded to H.264 MP4 with a maximum bitrate of 1300kbps and framerate of 120fps. Only one video can be attached, per post.
* **Audio** (MP3, OGG, WAV, FLAC, OPUS, AAC, M4A, 3GP) **up to 99MB**. Audio will be transcoded to MP3 using V2 VBR (roughly 192kbps). Only one audio file can be attached, per post.
#### Editing media {#edit}

View File

@ -79,7 +79,7 @@ If you want to see posts that are boosted multiple times be reinserted into your
Posts default to public privacy. You can choose to default new posts as unlisted or followers-only instead. For an explanation of post privacy levels, see [Posting to your Mastodon profile &gt; Publishing levels](../posting#privacy).
By default, the language of your posts is automatically detected, but this detection is imprecise and may not be accurate. If you primarily or exclusively post in a certain language, it is a good idea to set that language here.
If you primarily or exclusively post in a certain language, it is a good idea to set that language here.
If you often post sensitive media, you can choose to always mark your media as sensitive.

View File

@ -33,7 +33,8 @@ Your header is a banner image shown at the top of your profile, as well as in pr
You can set certain flags on your profile to let others know how you use Mastodon.
![]({{ relUrl "/assets/bot-flag.jpg" }})
{{< figure src="assets/bot-flag.jpg" caption="Overview of a profile with the Bot flag set." >}}
### Locked account {#locked}

View File

@ -50,6 +50,8 @@ There exist a number of **dedicated Mastodon hosting providers** that take care
{{< caption-link url="https://cloudplane.org" caption="Cloudplane" >}}
{{< caption-link url="https://ungleich.ch/u/products/mastodon-hosting/" caption="ungleich.ch" >}}
Managed hosting solutions are great for those who do not have experience or desire to install and maintain software. However, being in charge of all components on your own hardware gives greater control over scaling, performance and customization.
We provide a **DigitalOcean 1-Click Install Image** that you can put on a DigitalOcean droplet of your choosing which essentially gives you everything you would otherwise have after following our installation instructions through an interactive setup wizard.

View File

@ -92,7 +92,7 @@ Mastodon使用环境变量作为其的配置。
* `CACHE_REDIS_URL`
* `CACHE_REDIS_NAMESPACE`
### ElasticSearch {#elasticsearch}
### Elasticsearch {#elasticsearch}
* `ES_ENABLED`
* `ES_HOST`

View File

@ -1,23 +1,23 @@
---
title: 全文搜索
description: 设置ElasticSearch来搜索自己发出的嘟文、自己喜欢的嘟文、自己的书签和自己被提及的嘟文。
description: 设置Elasticsearch来搜索自己发出的嘟文、自己喜欢的嘟文、自己的书签和自己被提及的嘟文。
menu:
docs:
weight: 10
parent: admin-optional
---
当有可用ElasticSearch时Mastodon支持全文搜索。Mastodon的全文搜索允许登录用户从他们自己的嘟文、他们喜欢的嘟文、他们的书签和他们被提及的嘟文中查找相应结果。Mastodon有意禁用了在全数据库搜索任意关键词的功能。
当有可用Elasticsearch时Mastodon支持全文搜索。Mastodon的全文搜索允许登录用户从他们自己的嘟文、他们喜欢的嘟文、他们的书签和他们被提及的嘟文中查找相应结果。Mastodon有意禁用了在全数据库搜索任意关键词的功能。
## 安装 ElasticSearch {#install}
## 安装 Elasticsearch {#install}
ElasticSearch 需要 Java runtime。如果你还没有安装 Java请立刻安装上它。以下操均假定你已经登录为`root`用户:
Elasticsearch 需要 Java runtime。如果你还没有安装 Java请立刻安装上它。以下操均假定你已经登录为`root`用户:
```bash
apt install openjdk-8-jre-headless
```
添加ElasticSearch官方软件仓库至apt
添加Elasticsearch官方软件仓库至apt
```bash
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add -
@ -25,20 +25,20 @@ echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | tee -a /e
apt update
```
现在,你可以安装 ElasticSearch
现在,你可以安装 Elasticsearch
```bash
apt install elasticsearch
```
{{< hint style="warning" >}}
**安全警告:** 默认情况下ElasticSearch仅绑定于localhost即无法从外部网络访问。你可以通过查看 `/etc/elasticsearch/elasticsearch.yml` 中的 `network.host` 来检查 ElasticSearch 绑定了哪些地址。考虑到由于缺乏认证层,任何能访问 ElasticSearch 的人都可以读取或修改里面的数据。因此,确保访问安全非常重要。如[主要安装说明](../../prerequisites/#install-a-firewall-and-only-whitelist-ssh-http-and-https-ports)中所述防火墙建议仅暴露了22、80、443端口。如果你是一个多主机配置你必须知道如何保证内部流量安全。
**安全警告:** 默认情况下Elasticsearch仅绑定于localhost即无法从外部网络访问。你可以通过查看 `/etc/elasticsearch/elasticsearch.yml` 中的 `network.host` 来检查 Elasticsearch 绑定了哪些地址。考虑到由于缺乏认证层,任何能访问 Elasticsearch 的人都可以读取或修改里面的数据。因此,确保访问安全非常重要。如[主要安装说明](../../prerequisites/#install-a-firewall-and-only-whitelist-ssh-http-and-https-ports)中所述防火墙建议仅暴露了22、80、443端口。如果你是一个多主机配置你必须知道如何保证内部流量安全。
{{< /hint >}}
{{< hint style="danger" >}}
**安全警告:** 由于近期ElasticSearch所使用的`log4j`库被披露出[安全漏洞](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228),使用了旧版本`log4j`(`2.0`到`2.14.1`)的ES可能会受到影响。如果使用了这些版本的`log4j`,请参阅 [此 issue](https://github.com/elastic/elasticsearch/issues/81618#issuecomment-991000240) 来暂时缓解此问题。
**安全警告:** 由于近期Elasticsearch所使用的`log4j`库被披露出[安全漏洞](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228),使用了旧版本`log4j`(`2.0`到`2.14.1`)的ES可能会受到影响。如果使用了这些版本的`log4j`,请参阅 [此 issue](https://github.com/elastic/elasticsearch/issues/81618#issuecomment-991000240) 来暂时缓解此问题。
{{< /hint >}}
启动 ElasticSearch
启动 Elasticsearch
```bash
systemctl enable elasticsearch
@ -55,10 +55,10 @@ ES_HOST=localhost
ES_PORT=9200
```
如果你同一台机器上运行多个Mastodon服务器你计划让它们使用同一个ElasticSearch请确保他们都配置了互不重复的 `REDIS_NAMESPACE` 以分别他们的索引。如果你需要覆盖ElasticSearch索引前缀你可以直接设置 `ES_PREFIX`
如果你同一台机器上运行多个Mastodon服务器你计划让它们使用同一个Elasticsearch请确保他们都配置了互不重复的 `REDIS_NAMESPACE` 以分别他们的索引。如果你需要覆盖Elasticsearch索引前缀你可以直接设置 `ES_PREFIX`
保存新设置之后使用如下命令创建ElasticSearch索引
保存新设置之后使用如下命令创建Elasticsearch索引
```bash
RAILS_ENV=production bundle exec rake chewy:upgrade
@ -71,7 +71,7 @@ systemctl restart mastodon-sidekiq
systemctl reload mastodon-web
```
现在新的嘟文将会被写入ElasticSearch索引。最后一步是导入所有旧有数据。这将花费很长一段时间
现在新的嘟文将会被写入Elasticsearch索引。最后一步是导入所有旧有数据。这将花费很长一段时间
```bash
RAILS_ENV=production bundle exec rake chewy:sync
@ -85,10 +85,10 @@ RAILS_ENV=production bundle exec rake chewy:sync
### 中文搜索优化 {#chinese-search-optimize}
ElasticSearch默认使用标准分析器这对于中文来说可能并不太适合。为了提高搜索体验你可以安装特定语言的专用分析器。在创建ElasticSearch索引之前执行
Elasticsearch默认使用标准分析器这对于中文来说可能并不太适合。为了提高搜索体验你可以安装特定语言的专用分析器。在创建Elasticsearch索引之前执行
安装 [elasticsearch-analysis-ik](https://github.com/medcl/elasticsearch-analysis-ik)、[elasticsearch-analysis-stconvert](https://github.com/medcl/elasticsearch-analysis-stconvert) 插件至 ElasticSearch。
安装 [elasticsearch-analysis-ik](https://github.com/medcl/elasticsearch-analysis-ik)、[elasticsearch-analysis-stconvert](https://github.com/medcl/elasticsearch-analysis-stconvert) 插件至 Elasticsearch。
并对源码做出如下修改:

View File

@ -259,7 +259,7 @@ Redis被广泛使用于应用但是某些用途比其他用途更重要。主
为了减轻你的Postgresql服务器负担你可以使用热流复制hot streaming replication只读副本read replica。有关示例请参见[该指南](https://cloud.google.com/community/tutorials/setting-up-postgres-hot-standby)。你可以给以下Mastodon用途使用副本replica
* streaming API 服务器无需写入因此你可以将其直接使用副本replica。但由于 streaming API 服务器不经常查询数据库,这样的优化影响很小。
* 使用 Makara 驱动 web 与 sidekiq 进程这样可以实现从主master数据库写从副本replica读。让我们开始吧。
* 使用 Makara 驱动 web 与 sidekiq 进程,这样可以实现从主(primary数据库写从副本replica读。让我们开始吧。
编辑 `config/database.yml` 文件,将 `production` 替换为如下内容:

View File

@ -23,7 +23,7 @@ RAILS_ENV=production bin/tootctl help
## 基础命令
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/cli.rb" caption="lib/cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/base.rb" caption="lib/mastodon/cli/base.rb" >}}
### `tootctl self-destruct` {#self-destruct}
@ -51,7 +51,7 @@ RAILS_ENV=production bin/tootctl help
## 帐户相关命令 {#accounts}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/accounts_cli.rb" caption="lib/mastodon/accounts_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/accounts.rb" caption="lib/mastodon/cli/accounts.rb" >}}
### `tootctl accounts rotate` {#accounts-rotate}
@ -208,7 +208,7 @@ RAILS_ENV=production bin/tootctl help
## 缓存相关命令 {#cache}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/cache_cli.rb" caption="lib/mastodon/cache_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/cache.rb" caption="lib/mastodon/cli/cache.rb" >}}
### `tootctl cache clear` {#cache-clear}
@ -232,7 +232,7 @@ RAILS_ENV=production bin/tootctl help
## 域名相关命令 {#domains}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/domains_cli.rb" caption="lib/mastodon/domains_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/domains.rb" caption="lib/mastodon/cli/domains.rb" >}}
### `tootctl domains purge` {#domains-purge}
@ -269,7 +269,7 @@ RAILS_ENV=production bin/tootctl help
## Emoji相关命令 {#emoji}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/emoji_cli.rb" caption="lib/mastodon/emoji_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/emoji.rb" caption="lib/mastodon/cli/emoji.rb" >}}
### `tootctl emoji import` {#emoji-import}
@ -301,7 +301,7 @@ RAILS_ENV=production bin/tootctl help
## 时间流Feeds相关命令 {#feeds}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/feeds_cli.rb" caption="lib/mastodon/feeds_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/feeds.rb" caption="lib/mastodon/cli/feeds.rb" >}}
### `tootctl feeds build` {#feeds-build}
@ -327,7 +327,7 @@ RAILS_ENV=production bin/tootctl help
## 媒体相关命令 {#media}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/media_cli.rb" caption="lib/mastodon/media_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/media.rb" caption="lib/mastodon/cli/media.rb" >}}
### `tootctl media remove` {#media-remove}
@ -390,7 +390,7 @@ RAILS_ENV=production bin/tootctl help
## 预览卡片Preview Cards相关命令 {#preview_cards}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/preview_cards_cli.rb" caption="lib/mastodon/preview_cards_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/preview_cards.rb" caption="lib/mastodon/cli/preview_cards.rb" >}}
### `tootctl preview_cards remove` {#preview_cards-remove}
@ -409,11 +409,11 @@ RAILS_ENV=production bin/tootctl help
## 搜索相关命令 {#search}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/search_cli.rb" caption="lib/mastodon/search_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/search.rb" caption="lib/mastodon/cli/search.rb" >}}
### `tootctl search deploy` {#search-deploy}
创建或更新ElasticSearch索引并进行填充。 如果ElasticSearch为空此命令将创建必要的索引然后将数据从数据库导入到这些索引中。如果自上次运行以来索引结构已更改此命令还将升级索引。
创建或更新Elasticsearch索引并进行填充。 如果Elasticsearch为空此命令将创建必要的索引然后将数据从数据库导入到这些索引中。如果自上次运行以来索引结构已更改此命令还将升级索引。
**版本历史:**
* 2.8.0 - 被加入
@ -425,7 +425,7 @@ RAILS_ENV=production bin/tootctl help
## 站点设定相关命令 {#settings}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/settings_cli.rb" caption="lib/mastodon/settings_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/settings.rb" caption="lib/mastodon/cli/settings.rb" >}}
### `tootctl settings registrations open` {#settings-registrations-open}
@ -443,7 +443,7 @@ RAILS_ENV=production bin/tootctl help
## 嘟文相关命令 {#statuses}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/master/lib/mastodon/statuses_cli.rb" caption="lib/mastodon/statuses_cli.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/lib/mastodon/cli/statuses.rb" caption="lib/mastodon/cli/statuses.rb" >}}
### `tootctl statuses remove` {#statuses-remove}

View File

@ -7,7 +7,7 @@ menu:
---
{{< hint style="info" >}}
当一个新的Mastodon版本释出后它将出现在[GitHub releases页面](https://github.com/mastodon/mastodon/releases)。请注意:运行来自`master`分支的未释出代码,虽然可以进行,但不推荐这样做。
当一个新的Mastodon版本释出后它将出现在[GitHub releases页面](https://github.com/mastodon/mastodon/releases)。请注意:运行来自`main`分支的未释出代码,虽然可以进行,但不推荐这样做。
{{< /hint >}}
Mastodon版本与git tags一致。在尝试升级之前请至[GitHub releases页面](https://github.com/mastodon/mastodon/releases)查找所需版本。该页面包含了一个**更新日专**,其中描述你需要了解的所有差异,以及**特定的升级指令**。

View File

@ -32,7 +32,7 @@
</div>
<p class="legal legal--right">
<a href='https://joinmastodon.org'>{{ i18n "joinMastodon" }}</a> · <a href='https://blog.joinmastodon.org'>{{ i18n "blog" }}</a> · <a href='https://mastodon.social/@Mastodon' target='_blank'><i class='fab fa-mastodon'></i></a> · <a href='https://twitter.com/joinmastodon' rel='nofollow' target='_blank'><i class='fab fa-twitter'></i></a>
<a href='https://joinmastodon.org'>{{ i18n "joinMastodon" }}</a> · <a href='https://blog.joinmastodon.org'>{{ i18n "blog" }}</a> · <a href='https://mastodon.social/@Mastodon' target='_blank'><i class='fab fa-mastodon'></i></a>
</p>
<p class="legal">{{ with .File }}<a href='https://github.com/mastodon/documentation/tree/master/content/{{ .Lang }}/{{ .File.Path }}'>{{ i18n "viewSource" }}</a> · {{ end }}<a href='https://creativecommons.org/licenses/by-sa/4.0/'>CC BY-SA 4.0</a> · <a href='https://joinmastodon.org/imprint'>{{ i18n "imprint" }}</a></p>

View File

@ -1,6 +1,6 @@
<figure>
<p>
<strong>翻译状态:</strong>
本文是英文页面 <a href="{{ .Get "raw_link" }}">{{ .Get "raw_title" }}</a> 的翻译,最后翻译时间:{{ .Get "last_tranlation_time" }},点击<a href="https://github.com/mastodon/documentation/compare/{{ .Get "raw_commit" }}...master">这里</a>可以查看翻译后页面的改动。
本文是英文页面 <a href="{{ .Get "raw_link" }}">{{ .Get "raw_title" }}</a> 的翻译,最后翻译时间:{{ .Get "last_translation_time" }},点击<a href="https://github.com/mastodon/documentation/compare/{{ .Get "raw_commit" }}...master">这里</a>可以查看翻译后页面的改动。
</p>
</figure>

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB