From 2191e21480441af3473f2c60acb1417152bec184 Mon Sep 17 00:00:00 2001 From: Daniel Dizdarevic Date: Sun, 28 Jul 2024 23:13:53 +0200 Subject: [PATCH] Add option for customizing the status length --- README.md | 29 +++++++------- RELEASE.md | 8 ++-- snap/hooks/configure | 13 ++++++- snap/snapcraft.yaml | 3 +- src/mastodon/bin/setup | 8 ++++ src/mastodon/mastodon.env | 80 ++++++++++++++++++++++++++++----------- src/snap/snap.env | 1 + 7 files changed, 98 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 5cb82e0..ed2852d 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,8 @@ An initial setup command is required to initialize the database and configuratio sudo mastodon-server.setup +> Note: Be patient if you have changed the `status.char-limit`, as it takes some time to recompile the assets. + ## Create admin user Once the snap is set up, an administrator account with a randomly generated password can be created using the `tootctl` command: @@ -113,24 +115,25 @@ Basic settings can be configured using key-value pairs: The following settings are available: -| Key | Values | Default value | Description | -|----------------------|-------------------------------|------------------------|-----------------------------------------------------------------------| -| `domain` | valid FQDN | | FQDN of the Mastodon instance | -| `email` | valid e-mail | | E-mail address of the owner of the Mastodon instance | -| `ports.http` | 0 to 65353 | 80 | HTTP port | -| `ports.https` | 0 to 65353 | 443 | HTTPS port | -| `acme.server` | letsencrypt, zerossl | letsencrypt | CA used for acquiring an SSL certificate | +| Key | Values | Default value | Description | +|----------------------|-------------------------------|------------------------|--------------------------------------------------------------------------------------| +| `domain` | valid FQDN | | FQDN of the Mastodon instance | +| `email` | valid e-mail | | E-mail address of the owner of the Mastodon instance | +| `status.char-limit` | integer | 500 | Character limit of statuses (toots); changes require recompilation of assets, which takes some time | +| `ports.http` | 0 to 65353 | 80 | HTTP port | +| `ports.https` | 0 to 65353 | 443 | HTTPS port | +| `acme.server` | letsencrypt, zerossl | letsencrypt | CA used for acquiring an SSL certificate | | `update.backups` | true, false | true | Create a backup in `/var/snap/mastodon-server/common/update/backups` before updating | -| `media.dir` | absolute path | `$SNAP_COMMON/media` | Location of the media directory (*public/system*) | -| `backup.dir` | absolute path | `$SNAP_COMMON/backups` | Location of the backup directory | -| `backup.days` | integer | 0 | Create and keep backups for `backup.days` (enabled if > 0) | -| `cleanup.days` | integer | 7 | Cleanup media and statuses older than `cleanup.days` (enabled if > 0) | +| `media.dir` | absolute path | `$SNAP_COMMON/media` | Location of the media directory (*public/system*) | +| `backup.dir` | absolute path | `$SNAP_COMMON/backups` | Location of the backup directory | +| `backup.days` | integer | 0 | Create and keep backups for `backup.days` (enabled if > 0) | +| `cleanup.days` | integer | 7 | Cleanup media and statuses older than `cleanup.days` (enabled if > 0) | | `cleanup.media` | true, false | true | Cleanup media files, see [tootctl media remove](https://docs.joinmastodon.org/admin/tootctl/#media-remove) | | `cleanup.previews` | true, false | true | Cleanup preview cards, see [tootctl preview_cards remove](https://docs.joinmastodon.org/admin/tootctl/#preview_cards) | | `cleanup.statuses` | true, false | true | Cleanup unreferenced statuses, see [tootctl statuses remove](https://docs.joinmastodon.org/admin/tootctl/#statuses-remove) | | `cleanup.orphans` | true, false | false | Cleanup orphaned media files, see [tootctl media remove-orphans](https://docs.joinmastodon.org/admin/tootctl/#media-remove-orphans) | -| `log.access.enabled` | true, false | false | Logging of http(s) accesses | -| `log.access.format` | standard, anonymized, privacy | anonymized | Use of real/anonymized/no IP addresses in the access log | +| `log.access.enabled` | true, false | false | Logging of http(s) accesses | +| `log.access.format` | standard, anonymized, privacy | anonymized | Use of real/anonymized/no IP addresses in the access log | Configuration files can be used for advanced customization. diff --git a/RELEASE.md b/RELEASE.md index dca8706..56b607e 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -24,9 +24,7 @@ This release contains: * mastodon-bird-ui 1.8.5 * tangerine-ui 1.9.5 -Changelog for 4.2.10snap2: +Changelog for 4.2.10snap3: -* The PostgreSQL log file now has permissions that allow it to be rotated by logrotate. -* The snap now correctly detects and handles updates where the PostgreSQL major version changes. -* Huge pages are disabled in PostgreSQL because it does not have access to mmap in snap. -* Redis is prevented from trying to access the current_clocksource file on every restart, which is not possible in snap. +* Adds an option to change the character limit of toots (`status.characters`). +* Updates the browserlist DB for npm and yarn on build (see https://github.com/browserslist/update-db#readme) diff --git a/snap/hooks/configure b/snap/hooks/configure index 5e7e6db..e3c2684 100644 --- a/snap/hooks/configure +++ b/snap/hooks/configure @@ -3,11 +3,13 @@ . "$SNAP/nginx.env" . "$SNAP/mastodon.env" +export CURRENT_DOMAIN="$(mastodon_get_var LOCAL_DOMAIN)" export CURRENT_HTTP_PORT="$(nginx_get_http_port)" export CURRENT_HTTPS_PORT="$(nginx_get_https_port)" export CURRENT_NGINX_ACCESS_LOG="$(nginx_get_access_log)" export CURRENT_MEDIA_DIR="$(readlink -f $SNAP_DATA/mastodon/public/system)" export CURRENT_BACKUP_DIR="$(get_backup_dir_file)" +export CURRENT_STATUS_MAX_CHARS="$(get_status_max_chars_file)" if [ "$NGINX_ACCESS_LOG" != "$CURRENT_NGINX_ACCESS_LOG" ]; then restart_required nginx @@ -33,12 +35,19 @@ if [ "$BACKUP_DIR" != "$CURRENT_BACKUP_DIR" ]; then fi if $(mastodon_config_exists); then - export CURRENT_DOMAIN="$(mastodon_get_var LOCAL_DOMAIN)" - if [ "$DOMAIN" != "$CURRENT_DOMAIN" ]; then echo_error "DOMAIN cannot be changed safely! Setup a new instance if you really want to change it." exit 1 fi + + if [ "$STATUS_MAX_CHARS" != "$CURRENT_STATUS_MAX_CHARS" ]; then + echo Update status character limit + update_status_max_chars + recompile_assets + + restart_required backend + restart_required sidekiq + fi fi echo Restart services diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 6a86d24..cd97f66 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -9,7 +9,7 @@ description: | implements ActivityPub!) base: core20 -version: 4.2.10snap2 +version: 4.2.10snap3 grade: stable confinement: strict @@ -747,6 +747,7 @@ parts: bundle config build.openssl --with-openssl-dir=$SNAPCRAFT_STAGE/openssl1 bundle config build.pg --with-pg-config=$SNAPCRAFT_STAGE/postgres/bin/pg_config bundle install -j"$(nproc)" + npx browserslist@latest --update-db --yes yarn install --pure-lockfile yarn cache clean bundle exec rails assets:precompile diff --git a/src/mastodon/bin/setup b/src/mastodon/bin/setup index dba7995..c973b55 100755 --- a/src/mastodon/bin/setup +++ b/src/mastodon/bin/setup @@ -26,6 +26,14 @@ $SNAP/bin/psql.wrapper -d "$MASTODON_DBNAME" -c "create extension pg_stat_statem echo Remove old logs and tempfiles mastodon_rails log:clear tmp:clear +if [ "$STATUS_MAX_CHARS" != "$(get_status_max_chars_file)" ]; then + echo Update status character limit + update_status_max_chars + echo "Recompile assets (this takes some time)" + # TODO: Remove > /dev/null after update to Mastodon 4.3 + recompile_assets > /dev/null +fi + echo Restart services snapctl restart "$SNAP_NAME.backend" snapctl restart "$SNAP_NAME.streaming" diff --git a/src/mastodon/mastodon.env b/src/mastodon/mastodon.env index efffdcd..b89dee4 100644 --- a/src/mastodon/mastodon.env +++ b/src/mastodon/mastodon.env @@ -20,6 +20,8 @@ export BUNDLE_GEMFILE="$SNAP_DATA/mastodon/Gemfile" export BUNDLE_RAKEFILE="$SNAP_DATA/mastodon/Rakefile" export GEM_HOME="$SNAP_DATA/mastodon/vendor/ruby" export GEM_PATH="$GEM_HOME" +export YARN_RC_FILENAME="$SNAP_DATA/mastodon/.yarnrc.yml" +export YARN_CACHE_FOLDER=/tmp/yarn/cache export UPDATE_BACKUPS="$(snapctl get update.backups)" export MEDIA_DIR="$(snapctl get media.dir)" @@ -30,6 +32,38 @@ export CLEANUP_MEDIA="$(snapctl get cleanup.media)" export CLEANUP_PREVIEWS="$(snapctl get cleanup.previews)" export CLEANUP_STATUSES="$(snapctl get cleanup.statuses)" export CLEANUP_ORPHANS="$(snapctl get cleanup.orphans)" +export STATUS_MAX_CHARS="$(snapctl get status.char-limit)" + +compose_form="$SNAP_DATA/mastodon/app/javascript/mastodon/features/compose/components/compose_form.jsx" +status_length_validator="$SNAP_DATA/mastodon/app/validators/status_length_validator.rb" + +mastodon_config_exists() { + if [ -f "$SNAP_COMMON/mastodon.conf" ]; then + return 0 + else + return 1 + fi +} + +mastodon_set_var() { + if $(mastodon_config_exists); then + sed -i "s|^$1=.*\$|$1=$2|" "$SNAP_COMMON/mastodon.conf" + else + echo_error "$SNAP_COMMON/mastodon.conf does not exist." + exit 1 + fi +} + +mastodon_get_var() { + if $(mastodon_config_exists); then + sed -rn "s/$1=(.*)/\1/p" "$SNAP_COMMON/mastodon.conf" + fi +} + +if mastodon_config_exists; then + export SECRET_KEY_BASE="$(mastodon_get_var SECRET_KEY_BASE)" + export OTP_SECRET="$(mastodon_get_var OTP_SECRET)" +fi mastodon_rake() { cd "$SNAP_DATA/mastodon" && bundle exec rake -f "$BUNDLE_RAKEFILE" "$@" @@ -43,6 +77,11 @@ mastodon_node() { cd "$SNAP_DATA/mastodon" && node "$@" } +mastodon_yarn() { + mkdir -p "$YARN_CACHE_FOLDER" + cd "$SNAP_DATA/mastodon" && yarn "$@" +} + mastodon_sidekiq() { cd "$SNAP_DATA/mastodon" && bundle exec sidekiq "$@" } @@ -51,14 +90,6 @@ mastodon_tootctl() { cd "$SNAP_DATA/mastodon" && bundle exec tootctl "$@" } -mastodon_config_exists() { - if [ -f "$SNAP_COMMON/mastodon.conf" ]; then - return 0 - else - return 1 - fi -} - check_setup() { if ! $(mastodon_config_exists); then echo "Mastodon is not yet set up" @@ -72,21 +103,6 @@ setup_mastodon_database() { psql.wrapper -c "alter user $MASTODON_DBUSER createdb;" } -mastodon_set_var() { - if $(mastodon_config_exists); then - sed -i "s|^$1=.*\$|$1=$2|" "$SNAP_COMMON/mastodon.conf" - else - echo_error "$SNAP_COMMON/mastodon.conf does not exist." - exit 1 - fi -} - -mastodon_get_var() { - if $(mastodon_config_exists); then - sed -rn "s/$1=(.*)/\1/p" "$SNAP_COMMON/mastodon.conf" - fi -} - generate_mastodon_secrets() { eval $(mastodon_rake mastodon:webpush:generate_vapid_key) export SECRET_KEY_BASE="$(mastodon_rake secret)" @@ -139,3 +155,21 @@ mastodon_announcement() { psql.wrapper -d $MASTODON_DBNAME -c "insert into announcements (text, created_at, updated_at, published) values ('$1', now(), now(), '${2:-f}');" fi } + +recompile_assets() { + mkdir -p "$YARN_CACHE_FOLDER" + mastodon_rails assets:precompile +} + +get_status_max_chars_file() { + sed -rn "s/MAX_CHARS = ([0-9]+)/\1/p" "$status_length_validator" +} + +update_status_max_chars() { + if [ -n "$STATUS_MAX_CHARS" ] && [ "$STATUS_MAX_CHARS" -eq "$STATUS_MAX_CHARS" ] && [ "$STATUS_MAX_CHARS" -gt "0" ]; then + sed -ri "s/length\(fulltext\) > [0-9]+/length(fulltext) > $STATUS_MAX_CHARS/" "$compose_form" + sed -ri "s/CharacterCounter max=\{[0-9]+\}/CharacterCounter max={$STATUS_MAX_CHARS}/" "$compose_form" + sed -ri "s/MAX_CHARS = [0-9]+/MAX_CHARS = $STATUS_MAX_CHARS/" "$status_length_validator" + fi +} + diff --git a/src/snap/snap.env b/src/snap/snap.env index 7f77aa8..0fa17ec 100644 --- a/src/snap/snap.env +++ b/src/snap/snap.env @@ -19,6 +19,7 @@ export DEFAULT_BACKUP_DIR="$SNAP_COMMON/backups" export SETTINGS=$(cat <<-END domain, email, +status.char-limit,500 ports.http,80 ports.https,443 acme.server,letsencrypt