# Description
Updates our dereferencer emoji handling to work asynchronously when going through the route of account or status dereferencing.
closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4485
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4486
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Fixes a panic when clientIP cannot be parsed in the rate limiting middleware, and warn logs the derived clientIP and a hint that reverse proxy may be misconfigured.
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4479
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4481
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Fixes `sql: no rows in result set` when trying to append approvedByURI to a reply that was sent impolitely and approved impolitely.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4478
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This PR adds a new section to the documentation to contain workarounds for running
GtS on slow hardware. Right now it only contains a procedure on how to run migrations
on a different database instance in case the original database is too slow to finish
a database migration in a timely manner.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4457
Co-authored-by: Daniël Franke <df@ponc.tech>
Co-committed-by: Daniël Franke <df@ponc.tech>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request adds a check to see whether interaction policy on a refreshed status is different from the interaction policy set on that status before, and updates the status with the new policy if it's changed.
Should fix a pesky issue where folks on v0.19.2 and above still can't interact with statuses they dereferenced before updating.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4474
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
fixes possible race condition of existing status being out-of-date in enrichStatus()
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4470
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
- github.com/ncruces/go-sqlite3
- codeberg.org/gruf/go-mempool
- codeberg.org/gruf/go-structr (changes related on the above) *
- codeberg.org/gruf/go-mutexes (changes related on the above) *
* this is largely just fiddling around with package internals in structr and mutexes to rely on changes in mempool, which added a new concurrency-safe pool
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4468
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
This pull request tries to optimize our status rethreading migration by using bulk updates + avoiding unnecessary writes, and doing the migration in one top-level loop and one stragglers loop, without the extra loop to copy thread_id over.
On my machine it runs at about 2400 rows per second on Postgres, now, and about 9000 rows per second on SQLite.
Tried *many* different ways of doing this, with and without temporary indexes, with different batch and transaction sizes, etc., and this seems to be just about the most performant way of getting stuff done.
With the changes, a few minutes have been shaved off migration time testing on my development machine. *Hopefully* this will translate to more time shaved off when running on a vps with slower read/write speed and less processor power.
SQLite before:
```
real 20m58,446s
user 16m26,635s
sys 5m53,648s
```
SQLite after:
```
real 14m25,435s
user 12m47,449s
sys 2m27,898s
```
Postgres before:
```
real 28m25,307s
user 3m40,005s
sys 4m45,018s
```
Postgres after:
```
real 22m31,999s
user 3m46,674s
sys 4m39,592s
```
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4459
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
stripping `<blockquote>` of all the margin looks a bit funky. this only removes the inline margin. in English this generally means that it won’t have horizontal margin but will still have vertical margin.
Closes#4466


## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes. (I ran `go test ./...` from the main dir, they passed with one exception related to thumbnail file size, most likely caused by testing on macOS)
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4465
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request updates some of our inconsistent metric naming, and adds an example Grafana dashboard using all the most up-to-date metrics names, and updates our docs to describe the latest way of setting up metrics.
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4362
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4055
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Co-authored-by: kim <grufwub@gmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4443
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
i'll keep this on a separate branch for now while i experiment with other possible alternatives, but for now both our hacky implementation especially, and more popular ones (like anubis) aren't looking too great on the deterrent front: https://github.com/eternal-flame-AD/pow-buster
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4433
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Just a quick fix to the frontend to use the account domain in the move helper namestring thingy, instead of the host.
closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4197
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4440
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Leave just a little bit of padding between media + caption, for the lads!
[image](/attachments/5802a3d1-15c6-4ca2-8de2-4a149ba69f54)
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4439
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request stubs out the trends and suggestions APIs, just returning empty arrays for all four of the added endpoints. This is to help clients show fewer errors. It does *not* signal any intention to actually implement these endpoints properly, though you never know.
closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4385
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4435
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
Change the type of "Delete header" / "Delete avatar" button to just "button" to prevent them from getting deleted if user presses Enter in the description field.
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4363
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Co-authored-by: ptrcnull <git@ptrcnull.me>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4436
Co-authored-by: ptrcnull <ptrcnull@noreply.codeberg.org>
Co-committed-by: ptrcnull <ptrcnull@noreply.codeberg.org>
# Description
Fix links and typos in docs and settings page:
* Fix https://codeberg.org/superseriousbusiness/gotosocial/issues/4328
* Fix https://codeberg.org/superseriousbusiness/gotosocial/issues/4360
Also fix broken issuetracker links as forgejo does not support search
queries like "label:bug"
The translation for Zh-cn still says "this project" according to google
translate, I only fixed the link.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4418
Co-authored-by: Markus Unterwaditzer <markus-tarpit+git@unterwaditzer.net>
Co-committed-by: Markus Unterwaditzer <markus-tarpit+git@unterwaditzer.net>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4409 by reattempting `scheduled_at` parsing using ISO8601 offset.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4431
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
~~Still WIP!~~
This PR allows v0.20.0 of GtS to be forward-compatible with the interaction request / authorization flow that will fully replace the current flow in v0.21.0.
Basically, this means we need to recognize LikeRequest, ReplyRequest, and AnnounceRequest, and in response to those requests, deliver either a Reject or an Accept, with the latter pointing towards a LikeAuthorization, ReplyAuthorization, or AnnounceAuthorization, respectively. This can then be used by the remote instance to prove to third parties that the interaction has been accepted by the interactee. These Authorization types need to be dereferencable to third parties, so we need to serve them.
As well as recognizing the above "polite" interaction request types, we also need to still serve appropriate responses to "impolite" interaction request types, where an instance that's unaware of interaction policies tries to interact with a post by sending a reply, like, or boost directly, without wrapping it in a WhateverRequest type.
Doesn't fully close https://codeberg.org/superseriousbusiness/gotosocial/issues/4026 but gets damn near (just gotta update the federating with GtS documentation).
Migrations tested on both Postgres and SQLite.
Co-authored-by: kim <grufwub@gmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4394
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
- reduces number of necessary function calls by moving log level checking out of the uninlineable `logf(...)` function and into each of its caller (which are all inlined). this in turn means the log level check is performed in-situ wherever a call to `log.Debug(...)` (etc) is made, reduce unnecessary calls when a certain log level is disabled.
- sets the http.Server{}.ErrorLog to output to our internal logging package (which in turn ensures it gets wrapped in either our logfmt or json log formatting)
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4415
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
the "lo" paging value wasn't always being set when loading statuses from the database. this seems to (potentially) fix an issue in tusky with list timelines showing repeated posts.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4407
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
This uses a much faster method of generating request IDs using an atomically updated counter instead of a mutex lock and read of /dev/random.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4405
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Added a missing whitespace in callback page template.
Co-authored-by: Karolis Pocius <kpocius@gmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4404
Co-authored-by: karolis <karolis@noreply.codeberg.org>
Co-committed-by: karolis <karolis@noreply.codeberg.org>
# Description
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4402
Co-authored-by: mkljczk <git@mkljczk.pl>
Co-committed-by: mkljczk <git@mkljczk.pl>
this improves handling of zero value keys. not something we bump into often, but a useful fix to have in place.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4390
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
- codeberg.org/gruf/go-bytesize v1.0.3 -> v1.0.4
- codeberg.org/gruf/go-kv/v2 v2.0.6 -> v2.0.7
- codeberg.org/gruf/go-mutexes v1.5.2 -> v1.5.3
- codeberg.org/gruf/go-structr v0.9.7 -> v0.9.8
- codeberg.org/gruf/go-ffmpreg v0.6.8 -> v0.6.9
- github.com/tomnomnom/linkheader HEAD@2018 -> HEAD@2025
all of the above codeberg.org/gruf updates are in preparation for Go1.25, except for bytesize, and also ffmpreg which is a rebuild with the latest version of ffmpeg (v5.1.7)
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4386
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
This PR bumps golangci-lint used by CI to the latest version and partially disables the `var-naming` rule, which complains about the `common` and `util` package names.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4372
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
I don't see an issue for this, but the endpoint used for creating filters simply didn't store the filter keywords/statuses in the DB.
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4376
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
This pull request implements the `blur` value of `filter_action` for status filtering. It was introduced by Mastodon 4.4.0. [Related docs update](https://github.com/mastodon/documentation/pull/1620)
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4371
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
An implementation of [`scheduled_statuses`](https://docs.joinmastodon.org/methods/scheduled_statuses/). Will fix#1006.
this is heavily WIP and I need to reorganize some of the code, working on this made me somehow familiar with the codebase and led to my other recent contributions
i told some fops on fedi i'd work on this so i have no choice but to complete it 🤷♀️
btw iirc my avatar presents me working on this branch
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4274
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
Adds JSON logging as an optional alternative log output format. In the process this moves our log formatting itself into a separate subpkg to make it more easily modular, and improves caller name getting with some calling function name caching.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4355
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
July is definitely over.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4359
Co-authored-by: daenney <git@noreply.sourcery.dny.nu>
Co-committed-by: daenney <git@noreply.sourcery.dny.nu>
This pull request adds a new theme that I've just put together after procrastinating for 7 or 8 months lol
I made this pull request mainly because tobi already considered adding it to GtS upstream 5 minutes after [I made a fedi post about it](https://gts.apicrim.es/@awoo/statuses/01K18MJ1SD56581TANEKAKA6GV) ^^" (does this technically count as "discussing the proposed change"? probably not-) (though to be fair, this shows a slightly older revision of the theme -- you can see the most current one on [one of my fedi accounts](https://gts.apicrim.es/@128293). (…also I think it's quite obvious that I took the Ecks Pee theme as a basis ><)
Co-authored-by: Jade Arson <awoo@wolfyja.de>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4348
Co-authored-by: Jade Arson <codeberg@wolfyja.de>
Co-committed-by: Jade Arson <codeberg@wolfyja.de>
updates our codeberg.org/gruf/go-kv log key-value formatting library to latest version, which comes with some maaaaaaajor speed boosts in the form of:
- very minimal reflect.Value{} usage
- caching prepared formatting functions per type
~~still a work-in-progress until i make a release tag on the go-kv repository, which itself is waiting on published benchmark results in the README and finishing writing some code comments~~
benchmarks so far show this to be ~3x faster than the "fmt" stdlib package on average, when run across a wide variety (106 different types) of test cases, while still creating more visually friendly log output and actually recursing down nested struct ptrs
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4341
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request implements xyz or fixes abc.
closes #(issue)
closes #(another issue)
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4344
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
This brings some performance improvements and SQLite 3.50.3.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4334
Co-authored-by: Daenney <git@noreply.sourcery.dny.nu>
Co-committed-by: Daenney <git@noreply.sourcery.dny.nu>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request implements support for reading avif images properly.
closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4330
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4331
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request fixes `InteractionType` incorrectly set for pre-approved interaction requests.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4325
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
Add flags to skip local testrig db setup and teardown, to allow somewhat easier testing of migrations. Documents env vars available to the testrig.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4317
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This pull request implements two new properties on ActivityPub actors: `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb`.
As documented, these properties allow actors to signal their preference for whether or not their posts should be hidden from unauthenticated web views (ie., web pages like the GtS frontend, web apps like the Mastodon frontend, web APIs like the Mastodon public timeline API, etc). This allows remote accounts to *opt in* to having their unlisted visibility posts shown in (for example) the replies section of the web view of a GtS thread. In future, we can also use these properties to determine whether we should show boosts of a remote actor's post on a GtS profile, and that sort of thing.
In keeping with our stance around privacy by default, GtS assumes `true` for `hidesCcPublicFromUnauthedWeb` if the property is not set on a remote actor, ie., hide unlisted/unlocked posts by default. `hidesToPublicFromUnauthedWeb` is assumed to be `false` if the property is not set on a remote actor, ie., show public posts by default.
~~WIP as I still want to work on the documentation for this a bit.~~
New props are already in the namespace document: https://gotosocial.org/ns
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4315
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4311
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
This finalizes the moving status filtering out of the type converter, and into its own `./internal/filter/` subpkg :)
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4306
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
The docs currently state that sending via `localhost` unencrypted can work but that's only true when the SMTP server doesn't offer `STARTTLS`. Make that a bit more obvious.
Couldn't test the doc build as miniconda isn't in my distro and pip wouldn't find all dependencies.
# Description
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Co-authored-by: Guido Günther <agx@sigxcpu.org>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4301
Co-authored-by: agx <agx@noreply.codeberg.org>
Co-committed-by: agx <agx@noreply.codeberg.org>
this adds another 'filter' type cache, similar to the visibility and mute caches, to cache the results of status filtering checks. for the moment this keeps all the check calls themselves within the frontend typeconversion code, but i may move this out of the typeconverter in a future PR (also removing the ErrHideStatus means of propagating a hidden status).
also tweaks some of the cache invalidation hooks to not make unnecessary calls.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4303
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Updates markdown parser + sanitizer to allow footnote anchors to work properly, with appropriate roles. Footnote anchor IDs and backrefs use the status ID as a prefix to avoid clashes, so that footnotes don't break when multiple footnoted statuses are rendered on the same page (eg., in a thread or on the account's home page).
closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4296
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4298
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
- removes unnecessary fields / columns (created_at, updated_at)
- replaces filter.context_* columns with singular filter.contexts bit field which should save both struct memory and database space
- replaces filter.action string with integer enum type which should save both struct memory and database space
- adds links from filter to filter_* tables with Filter{}.KeywordIDs and Filter{}.StatusIDs fields (this also means we now have those ID slices cached, which reduces some lookups)
- removes account_id fields from filter_* tables, since there's a more direct connection between filter and filter_* tables, and filter.account_id already exists
- refactors a bunch of the filter processor logic to save on code repetition, factor in the above changes, fix a few bugs with missed error returns and bring it more in-line with some of our newer code
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4277
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
also comments-out a flaky test, (or at-least part of it), since it's testing a pkg part that is already tested.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4285
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
This PR just fiddles with the order in which we process status create / boost / fave side effects and implicit acceptances. The goal is to try to make sure the Accept message gets sent to a remote instance *before* the interaction with an implicitly accepted status.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4282
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
Follow-up to #4270
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/3450
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4275
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
I recently noticed that pending interaction requests don't disappear on domain suspension.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4278
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Our extra `alsoKnownAs` inline `@context` entry was incorrect, and doesn't need to be included anyways as it's already present at the AS namespace context doc here: https://www.w3.org/ns/activitystreams. This PR just removes it :)
closes https://codeberg.org/superseriousbusiness/gotosocial/issues/3883
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4280
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This unwraps and follows the boosted status to do a full mute check on the original.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4276
Reviewed-by: tobi <kipvandenbos@noreply.codeberg.org>
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
This implementation is compatible with Iceshrimp.NET, Pleroma and Chuckya, which already support federated avatar/header descriptions. I will add support for incoming descriptions federation in this or another PR (depending on when this one gets merged).
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4270
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request adds logic for nicely handling retractions of entries from domain permission subscriptions.
See docs for how this works but basically retracted entries will either be removed (and possibly picked up by a lower-prio subscription), or orphaned (and then possibly adopted), depending on the config of the domain permission subscription.
closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4101
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4261
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This pull request closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4257 by removing the hardcoded "public" schema assumption in the database migrations. Tested on a local postgres with both the default public schema, and with the connection string (gotosocial schema) mentioned in the issue. Both seem to work OK!
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4269
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
Contribution guidelines link to the golangci-lint documentation for the up-to-date version rather than [the legacy v1 doc](https://golangci.github.io/legacy-v1-doc/), which uses a different configuration schema. I migrated the config using the `golangci-lint migrate` command, moved the comments, adjusted staticcheck config and ensured the rules still work.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4265
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
- updates account delete processing to handle side-effects synchronously to prevent OOM
- updates account delete processing to check more often if account.IsLocal() for certain deletes / side-effects
- ensures that mutes get removed from database on delete
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4260
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
- adds configuration for thumbnail maximum dimensions with warning on exceeding recommendations
- moves the media configuration vars into their own sub-struct
- replaces the configuration flag funcs with simple string consts
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4258
Reviewed-by: tobi <kipvandenbos@noreply.codeberg.org>
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Brings our parsing of unset sub-policies in line with the defaults documented here: https://docs.gotosocial.org/en/v0.19.1/federation/interaction_policy/#defaults-per-sub-policy
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4146
Part of https://codeberg.org/superseriousbusiness/gotosocial/issues/4026
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4229
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
Related to #4252. This fixes existing statuses with visibility enum set to 0, if any exist on the server, by replacing their visibility to direct (to not leak them outside the intended scope).
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4253
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
The current documentation states that the `protocol` configuration
option should only be changed to `http` for local testing, and that even
if running behind a reverse proxy, `https` should be used.
https://docs.gotosocial.org/en/latest/configuration/general/
As such, update the `protocol` option help text so that it does not
suggest using `http` when running behind a reverse proxy.
Signed-off-by: Oliver Calder <oliver@calder.dev>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4250
Co-authored-by: Oliver Calder <oliver@calder.dev>
Co-committed-by: Oliver Calder <oliver@calder.dev>
# Description
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4255
Co-authored-by: Daenney <daenney@noreply.codeberg.org>
Co-committed-by: Daenney <daenney@noreply.codeberg.org>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
closes#4247
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4252
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
This enables footnote support which is mentioned as allowed in the [user guide](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/docs/user_guide/posts.md#input-types). The regression was reported on Matrix.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [sort of] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4251
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
# Description
I'm not sure if this should be handled this way, but some of the TOC links don't work on Forgejo due to, I guess, the Markdown parser behavior. This, however, makes them not work on GitHub
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4223
Co-authored-by: Nicole Mikołajczyk <git@mkljczk.pl>
Co-committed-by: Nicole Mikołajczyk <git@mkljczk.pl>
# Description
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4240
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request updates our parsing of the `url` property in incoming ActivityPub items to also include Link items, and not just bare URIs.
The first discovered url is still used as the *gtsmodel.Account or *gtsmodel.Status `url` property, so this change only really affects our dereference URL anti-spoof check thingy.
~~Should fix https://codeberg.org/superseriousbusiness/gotosocial/issues/4248 but I need to run it and test it myself first to be sure.~~
Fixes https://codeberg.org/superseriousbusiness/gotosocial/issues/4248
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4249
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This is just a useful feature that it seemed more semantically correct to have in the storage library itself! Still, thank you to @vdyotte for the original change :)
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4246
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
A brief note on the above change: Go does not seem to like version tagging outside of `v?[0-9\.]` formatting, so it translates `ssb-v4.5.3-1` to `v4.5.4-0.20250606121655-9d54ef189d42` and as such sees it as a "downgrade" compared to the previous `v4.9.0`. which functionally isn't a problem, everything still behaves as it should, but it means people can't just run `go get repo@latest` for this particular dependency.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4245
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Does as it says on the tin! Should make things a bit easier for clients that don't provide an access token to the custom emojis endpoint.
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/2430
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4233
Reviewed-by: Daenney <daenney@noreply.codeberg.org>
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
As I noted in https://codeberg.org/superseriousbusiness/gotosocial/pulls/2224 the PKCE code challenge method of "plain" is insecure and its usage is not recommend. In Mastodon and Hollo, we do not support it, as indicated by the `code_challenge_methods_supported` value here: https://mastodon.social/.well-known/oauth-authorization-server
This pull request removes the support for PKCE code challenge method "plain".
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
I do get test failures locally, due to file sizes for media being different, but that's definitely unrelated to this change, as far as I can tell there is zero test coverage this part of the GTS code.
Co-authored-by: Emelia Smith <ThisIsMissEm@users.noreply.github.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4232
Co-authored-by: Emelia <thisismissem@noreply.codeberg.org>
Co-committed-by: Emelia <thisismissem@noreply.codeberg.org>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
# Description
This pull request adds a new endpoint which returns a list of pending follow requests requested by the user. The test is adapted from the GET /api/v1/follow_requests test.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4224
Co-authored-by: nicole mikołajczyk <git@mkljczk.pl>
Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
# Description
This pull request fixes a bug encountered when playing around with GTS code.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4222
Co-authored-by: Nicole Mikołajczyk <git@mkljczk.pl>
Co-committed-by: Nicole Mikołajczyk <git@mkljczk.pl>
# Description
Adds a configuration option to set the outgoing transport of HTTP requests for testing purposes.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
- Note: `go fmt` yes, golangci-lint fails, can't load any configuration
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4134
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: famfo <famfo@famfo.xyz>
Co-committed-by: famfo <famfo@famfo.xyz>
This separates our the user mute handling from the typeconverter code, and creates a new "mutes" filter type (in a similar vein to the visibility filter) subpkg with its own result cache. This is a heavy mix of both chore given that mute calculation shouldn't have been handled in the conversion to frontend API types, and a performance bonus since we don't need to load and calculate so many things each time, just the single result each time with all necessary invalidation handled by database cache hooks.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4202
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
Thank you in part to f0x for nerd-sniping me into banging this together :p
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4219
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
Upgrades ncruces/go-sqlite3 to 0.26 which includes SQLite 3.50.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4218
Co-authored-by: Daenney <daenney@noreply.codeberg.org>
Co-committed-by: Daenney <daenney@noreply.codeberg.org>
Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
# Description
This pull request fixes a typo.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4217
Co-authored-by: Nicole Mikołajczyk <git@mkljczk.pl>
Co-committed-by: Nicole Mikołajczyk <git@mkljczk.pl>
Been running these changes on on my live instance without any issues as far as I can tell. It's been playing nice with multiple instances in the same bucket.
# Description
This lets users prefix their object storage files.
Useful for when you want to host multiple GTS instances inside
the same bucket. Providers like Backblaze limit the number of buckets
you can have on your account so grouping by prefix may be more desirable
in this situation.
closes#1371
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4200
Co-authored-by: vdyotte <vdyotte@gmail.com>
Co-committed-by: vdyotte <vdyotte@gmail.com>
That's it! It just conditionally imports prism light or prism dark depending on the theme.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4201
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This pull request adds four new themes with auto light/dark switching options too!
Tested for color contrast etc in firefox with all three local test rig accounts.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4199
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
- add a `migrations run` sub command to allow simply starting / stopping the db service, useful if you want to run *only* the migrations, both for testing or if you have a speedier box you want to run them on
- tweaks to log messages
- moved more stages outside of transactions, on sqlite if the transactions were getting too lengthy it could occasionally show an `sqlite: disk i/o error`
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4198
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
This is quite a complex database migration that updates the `statuses.thread_id` column to be notnull, in order that statuses always be threaded, which will be useful in various pieces of upcoming work. This is unfortunately a migration that acts over the entire statuses table, and is quite complex in order to ensure that all existing statuses get correctly threaded together, and where possible fix any issues of statuses in the same thread having incorrect thread_ids.
TODO:
- ~~update testrig models to all be threaded~~
- ~~update code to ensure thread_id is always set~~
- ~~run on **a copy** of an sqlite production database~~
- ~~run on **a copy** of a postgres production database~~
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4160
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
This updates our proof-of-work middleware, NoLLaMas, to work on a more easily configurable algorithm (thank you f0x for bringing this to my attention!). Instead of requiring that a solution with pre-determined number of '0' chars be found, it now pre-computes a result with a pre-determined nonce value that it expects the client to iterate up-to. (though with some level of jitter applied, to prevent it being too-easily gamed). This allows the user to configure roughly how many hash-encode rounds they want their clients to have to complete.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4186
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Just remove the dependency `test` has on `lint`, as it's not actually dependent on it, and has different triggers.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4189
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This pull request adds a very simple ad-hoc ListenBrainz widget to the frontend web view, with progressive enhancement (in all fail states it just falls back to rendering the field as normal).
This necessitated adding the ListenBrainz API endpoint to the `connect-src` part of our Content-Security-Policy header. We might want to tweak this to only add that endpoint to `connect-src` for profiles, and then only for profiles that include a ListenBrainz field, but this would require significant dicking about with the middleware, and checks inside the app logic, such that it might not be worthwhile (after all, we control all the scripts right now anyway).
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4184
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
* Set `go.mod` to 1.24 now that it's been out for 3 months.
* Update all the test to use `testing.T.Context()`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4187
Co-authored-by: Daenney <git@noreply.sourcery.dny.nu>
Co-committed-by: Daenney <git@noreply.sourcery.dny.nu>
- adds config flags `instance-expose-allowlist` and `instance-expose-allowlist-web` to allow instance admins to expose their allowlist via the web + api.
- renames `instance-expose-suspended` and `instance-expose-suspended-web` to `instance-expose-blocklist` and `instance-expose-blocklist-web`.
- deprecates the `suspended` filter on `/api/v1/instance/peers` endpoint and adds `blocked` and `allowed` filters
- adds the `flat` query param to `/api/v1/instance/peers` to allow forcing return of a flat list of domains
- implements `/api/v1/instance/domain_blocks` and `/api/v1/instance/domain_allows` endpoints with or without auth depending on config
- rejigs the instance about page to include a general section on domain permissions, with block and allow subsections (and appropriate links)
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/3847
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4150
Prerequisite to https://codeberg.org/superseriousbusiness/gotosocial/issues/3711
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4169
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
- moves preloader Done() function calling to be handled entirely by the preloader, not the caller
- adds tests for multiple preload success / failure / clear states
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4182
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
after seeing a potential reported federating worker lockup i decided to start digging into the federatingdb code. this PR encompasses:
- removes one of our last unused interface types `federatingdb.DB{}`, replacing it with a struct type `*federatingdb.DB{}`
- in `transport.dereferenceLocal()` differentiates between an unsupported lookup type and ErrNoEntries to reduce unnecessary calls, and reduce potential lockups that may occur while trying to call our own endpoints that then call `federatingdb.Lock()`
- removes a bunch of the locks on follow state changes since the DB already synchronizes that
- removes the unnecessary `pub.Clock{}` struct field and type passed to the transport controller
frankly it would be great if we could remove the locking in `federatingdb.Lock()` and instead handle it ourselves as it gets very confusing trying to figure out what functions will have locks held. but i guess that's one for when we move further away from the go-fed/activity/pub package usage.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4178
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
As discussed in Matrix chat.
* Change DB in example config to sqlite.
* Clarify config settings which only apply to postgres.
* Update getting started docs; no need to change example config any more.
* In "single board computers" mention SD card corruption risk.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [X] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [X] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [X] I/we have not leveraged AI to create the proposed changes.
- [X] I/we have performed a self-review of added code.
- [X] I/we have made any necessary changes to documentation.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4174
Co-authored-by: Phil Hagelberg <phil@hagelb.org>
Co-committed-by: Phil Hagelberg <phil@hagelb.org>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Profile fields, right? So I made them a configurable amount and show them on the instance features. Closes#1876
All changes I did are described in the commits. I tried to cover as much as possible, but I don't know this codebase to know what I've missed. I have tested it manually and it works (settings page, `/api/v1/instances`, server-side validation).
Not done:
- An "Add profile fields" button, so that instances with a high profile fields count (e.g. 100) aren't an issue when trying to skip the profile fields (in some form, accessibility)
- Updating the swagger docs that specify a specific amount of profile fields for the updating endpoint (not sure how to proceed with that)
- Unchecked checklist items
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [X] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [X] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [X] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [X] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [X] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Notes about checklist:
- ["Approval" to work on this reference](https://matrix.to/#/!mlPctfMHjyopbOnliM:superseriousbusiness.org/$P0Z1Qmny6GNIgxhre69gll8KSD690HC8nVvNpXmu3nU?via=superseriousbusiness.org&via=matrix.org&via=tchncs.de)
- `golangci-lint run` output ignored due to complaining about ffmpeg and some other code I didn't touch
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4175
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: Jackson <jackson@jacksonchen666.com>
Co-committed-by: Jackson <jackson@jacksonchen666.com>
This pull request deprecates `with_approval` and `always` on the client API side, and `approvalRequired` and `always` on the fedi API side, replacing them with `automatic_approval` and `manual_approval` and `automaticApproval` and `manualApproval`, respectively.
Back-compat is kept with these deprecated fields, and they're still serialized to the client API and fedi APIs respectively, in addition to the new non-deprecated properties.
This will stay the case until v0.21.0 when they'll be removed.
For the sake of not doing a massive database migration, the fields are still named `Always` and `WithApproval` in storage. I think this is probably fine!
Part of https://codeberg.org/superseriousbusiness/gotosocial/issues/4026
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4173
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This'll hopefully catch some straggler occurrences of the tests not wanting to run.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4177
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This pull request tidies up some previous migrations by making sure there's a proper snapshot in the migrations folder of what interaction policies looked like at the time the migration was written, rather than using the moving target `internal/gtsmodel`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4171
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
Switches the script to use the Codeberg API to retrieve the hash.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4151
Use correct input-field identifier for authorization page email label. This seemed to be only instance where label was broken, other labels either had correct for-identifier or enclosed the input which they are labeling.
closes#4165
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4166
Co-authored-by: Iivari Äikäs <iivari.aikas@gmail.com>
Co-committed-by: Iivari Äikäs <iivari.aikas@gmail.com>
# Description
This pull request adds `id` attributes to elements in the "About" section of the user page so that it is easy to look them up using css.
It also move the screen reader only elements for some these so that they are re-ordered alongside their parent element.
closes#4163
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4164
Co-authored-by: Frederic Thevenet <thevenet.fred@free.fr>
Co-committed-by: Frederic Thevenet <thevenet.fred@free.fr>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Update our opengraph meta tag code stuff:
- Use `audio` and `video` types where appropriate.
- Include fall back to `image` types.
- Include `twitter:card=summary` or `twitter:card=summary_large_image` where appropriate (closes https://codeberg.org/superseriousbusiness/gotosocial/issues/2776)
- Include avatar description where possible.
- Include mime type for media.
- Set `modified_time` properly based on latest edit time.
Examples
Status with one image attachment, that's been edited:
```html
<meta property="og:locale" content="en">
<meta property="og:type" content="article">
<meta property="og:title" content="Post by Kip Van Den Bos, salad enjoyer, @tobi@goblin.technology">
<meta property="og:url" content="https://goblin.technology/@tobi/statuses/01JE3BQPNHWNHSNM0KS78X321Q">
<meta property="og:site_name" content="goblin.technology">
<meta property="og:description" content="cowards: "I'll be a few minutes late, sorry!" me:">
<meta property="og:article:publisher" content="https://goblin.technology/@tobi">
<meta property="og:article:author" content="https://goblin.technology/@tobi">
<meta property="og:article:modified_time" content="2025-04-22T07:24:49.773Z">
<meta property="og:article:published_time" content="2024-12-02T09:37:58.449Z">
<meta property="og:image" content="https://goblin.technology/fileserver/016T5Q3SQKBT337DAKVSKNXXW1/attachment/original/01JE3BPJ1TGMV6H6E8VY0ED5XA.png">
<meta property="og:image:type" content="image/png">
<meta property="og:image:width" content="1224">
<meta property="og:image:height" content="368">
<meta property="og:image:alt" content="Screenshot of a signal conversation where I wrote "Just gonna smash out a quick poo" and my friend responded with a sad face.">
<meta property="og:image" content="https://goblin.technology/fileserver/016T5Q3SQKBT337DAKVSKNXXW1/attachment/original/01J4YBM16ES6C1ENKZC8MC04BD.gif">
<meta property="og:image:type" content="image/gif">
<meta property="og:image:width" content="38">
<meta property="og:image:height" content="49">
<meta property="og:image:alt" content="Avatar for tobi: A 90's style gif of a black and white skull chattering happily.">
<meta property="og:image" content="https://goblin.technology/fileserver/01BPSX2MKCRVMD4YN4D71G9CP5/attachment/original/01J387PFPNKQWWNY9YQM67WA1T.gif">
<meta property="og:image:type" content="image/gif">
<meta property="og:image:alt" content="Little green peglin goblin bouncing happily.">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://goblin.technology/fileserver/016T5Q3SQKBT337DAKVSKNXXW1/attachment/original/01JE3BPJ1TGMV6H6E8VY0ED5XA.png">
<meta name="twitter:image:alt" content="Screenshot of a signal conversation where I wrote "Just gonna smash out a quick poo" and my friend responded with a sad face.">
```
Status with one audio file (with thumbnail):
```html
<meta property="og:locale" content="en">
<meta property="og:type" content="article">
<meta property="og:title" content="Post by Kip Van Den Bos, salad enjoyer, @tobi@goblin.technology">
<meta property="og:url" content="https://goblin.technology/@tobi/statuses/01JSV5BQ585HB4R8NPK4ANTG91">
<meta property="og:site_name" content="goblin.technology">
<meta property="og:description" content="service top anthem imo">
<meta property="og:article:publisher" content="https://goblin.technology/@tobi">
<meta property="og:article:author" content="https://goblin.technology/@tobi">
<meta property="og:article:modified_time" content="2025-04-27T08:21:00.712Z">
<meta property="og:article:published_time" content="2025-04-27T08:21:00.712Z">
<meta property="og:audio" content="https://goblin.technology/fileserver/016T5Q3SQKBT337DAKVSKNXXW1/attachment/original/01JSV5AJ4RF3E6DATCSW8SAY93.mp3">
<meta property="og:audio:secure_url" content="https://goblin.technology/fileserver/016T5Q3SQKBT337DAKVSKNXXW1/attachment/original/01JSV5AJ4RF3E6DATCSW8SAY93.mp3">
<meta property="og:audio:type" content="audio/mpeg">
<meta property="og:audio:alt" content="Sanctified by Nine Inch Nails, from Pretty Hate Machine">
<meta property="og:image" content="https://goblin.technology/fileserver/016T5Q3SQKBT337DAKVSKNXXW1/attachment/small/01JSV5AJ4RF3E6DATCSW8SAY93.webp">
<meta property="og:image:type" content="image/webp">
<meta property="og:image:width" content="500">
<meta property="og:image:height" content="500">
<meta property="og:image:alt" content="Sanctified by Nine Inch Nails, from Pretty Hate Machine">
<meta property="og:image" content="https://goblin.technology/fileserver/016T5Q3SQKBT337DAKVSKNXXW1/attachment/original/01J4YBM16ES6C1ENKZC8MC04BD.gif">
<meta property="og:image:type" content="image/gif">
<meta property="og:image:width" content="38">
<meta property="og:image:height" content="49">
<meta property="og:image:alt" content="Avatar for tobi: A 90's style gif of a black and white skull chattering happily.">
<meta property="og:image" content="https://goblin.technology/fileserver/01BPSX2MKCRVMD4YN4D71G9CP5/attachment/original/01J387PFPNKQWWNY9YQM67WA1T.gif">
<meta property="og:image:type" content="image/gif">
<meta property="og:image:alt" content="Little green peglin goblin bouncing happily.">
<meta name="twitter:card" content="summary">
```
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4154
Reviewed-by: Daenney <daenney@noreply.codeberg.org>
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This pull request closes https://codeberg.org/superseriousbusiness/gotosocial/issues/3403 by searching for alt or title attributes in HTML, looking for the shortest indent (if any) at the start of multiline content of said attributes, and remove that shortest indent from each line. This is a bit more fiddly than the "easy" way of doing it, but it has the advantage that it preserves user-added indents at the start of lines of alt text.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4149
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Juggles our fonts around a bit to use subdirs for font families, and also updates atkinson hyperlegible to atkinson hyperlegible next, which includes monospace fonts.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4148
Reviewed-by: Daenney <daenney@noreply.codeberg.org>
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
This updates our configuration code generator to now also include map marshal and unmarshalers. So we now have much more control over how things get read from pflags, and stored / read from viper configuration. This allows us to set ALL configuration variables by CLI and environment now, AND support nested configuration files. e.g.
```yaml
advanced:
scraper-deterrence = true
http-client:
allow-ips = ["127.0.0.1"]
```
is the same as
```yaml
advanced-scraper-deterrence = true
http-client-allow-ips = ["127.0.0.1"]
```
This also starts cleaning up of our jumbled Configuration{} type by moving the advanced configuration options into their own nested structs, also as a way to show what it's capable of. It's worth noting however that nesting only works if the Go types are nested too (as this is how we hint to our code generator to generate the necessary flattening code :p).
closes#3195
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4109
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
Fixes a bug in the new timeline code in which the limit query parameter wasn't always being fulfilled, in which case some clients like Tusky would then assume it didn't need to add a "load more" placeholder view even when there were more statuses to be loaded. This also fiddles around a bit in the logging middleware handler to add some more code comments, and add logging of full request URIs when it is safe to do so.
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4141
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
This pull request implements the ability to specify the S3 bucket lookup type that is passed to the minio-go library. By default, minio-go uses a regex on the endpoint to see if it is a host that supports DNS access or not. Tigris and others are moving away from path style bucket access to DNS style bucket access using subdomains.
This keeps the default as 'auto' to allow existing users to not need to modify their configurations.
closes#3942
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4120
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: nopjmp <nop@unearthly.dev>
Co-committed-by: nopjmp <nop@unearthly.dev>
Daenney is a dummy and forgot to add these when he revamped the OTEL stuff.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4137
Co-authored-by: Daenney <daenney@noreply.codeberg.org>
Co-committed-by: Daenney <daenney@noreply.codeberg.org>
# Description
This simplifies our OTEL setup by:
* Getting rid of some deprecated things.
* Using `autoexport` and letting things get configured by the `OTEL_` environment variables.
* Removing all the unnecessary config options.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4110
Reviewed-by: tobi <kipvandenbos@noreply.codeberg.org>
Co-authored-by: Daenney <daenney@noreply.codeberg.org>
Co-committed-by: Daenney <daenney@noreply.codeberg.org>
Updates gotosocial-woodpecker-build to a version that includes goreleaser v2.9.0, which should work properly with "gitea" aka forgejo (ie., codeberg).
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4133
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
Adds a small notice to the Github README with when we intend to stop mirroring.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4128
Co-authored-by: daenney <daenney@noreply.codeberg.org>
Co-committed-by: daenney <daenney@noreply.codeberg.org>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request fixes an issue where multiple mentions were being created for one statuses, when delivered to multiple inboxes on an instance, but only the final mention ended up actually being used. Also adds tests to make sure that a notification is received when a status is edited to include a mention.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4127
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
CI_PIPELINE_FILES seems to be empty on force pushes to an open pull request, so this PR just accounts for that and runs all steps if it's the case, as we can't tell then what's actually changed.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4121
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
- replaces the sha256 calculation with an alternative implementation that seems to use more uniform time-taken across different platforms
- goes back to the simpler difficulty calculation without a "partial" difficulty level
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4096
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
While working on the doc translation update, I found a broken link. So I;m opening this separate PR to keep it clean from the translation stuff. Marked as draft currently for checking for any other typos :)
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4111
Co-authored-by: cdn0x12 <git@cdn0x12.dev>
Co-committed-by: cdn0x12 <git@cdn0x12.dev>
# Description
This PR updates the Chinese documentation to 6c879186 (the latest commit at present).
It also fixed a small typo in the original docs. Since the change is so minor, I didn't make a separate PR.
Last docs/zh update PR: #3884
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4117
Co-authored-by: cdn0x12 <git@cdn0x12.dev>
Co-committed-by: cdn0x12 <git@cdn0x12.dev>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Previously we were passing a *followers* URI into the federatingDB `Followers` function, which expects an *account* URI. This led to a nil body when doing internal dereferences (ie., while sending out messages). I think I probably wrote this bug when I refactored stuff a while ago.
This PR fixes that up by making the dereferenceLocal function more consistent, and falling back to an http dereference if nothing found. Clarifies behavior of the federatingdb.Get function as well, by commenting the shit out of it.
Also adds tests, precious tests.
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4066
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4097
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Updates our release flow to point at "gitea", which should work for Codeberg as well.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4100
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
closes https://codeberg.org/superseriousbusiness/gotosocial/issues/4049 by removing the silly defer statement. Adds a test too, and a warning in the docs.
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [x] I/we have made any necessary changes to documentation.
- [x] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4094
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
- tweaks the NoLLaMas proof-of-work algorithm to further granularity on time spent computing solutions
- standardizes GoToSocial cookie security directive setting in a CookiePolicy{} type
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4090
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
Removes the move check from the invalidate token API handler, as moved accounts should be able to delete their old tokens.
closes#4067
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4091
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
Tweak to show time taken when solving nollamas, and use a pulser rather than a spinner to indicate work being done.
Also use `window.location.replace` for doing the redirect instead of setting window.location.href: https://developer.mozilla.org/en-US/docs/Web/API/Location/replace
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4088
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
- moves it to the advanced section
- adds it to the mkdocs config
- adds warning about it not covering RSS endpoints
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4084
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
This adds a proof-of-work based scraper deterrence to GoToSocial's middleware stack on profile and status web pages. Heavily inspired by https://github.com/TecharoHQ/anubis, but massively stripped back for our own usecase.
Todo:
- ~~add configuration option so this is disabled by default~~
- ~~fix whatever weirdness is preventing this working with CSP (even in debug)~~
- ~~use our standard templating mechanism going through apiutil helper func~~
- ~~probably some absurdly small performance improvements to be made in pooling re-used hex encode / hash encode buffers~~ the web endpoints aren't as hot a path as API / ActivityPub, will leave as-is for now as it is already very minimal and well optimized
- ~~verify the cryptographic assumptions re: using a portion of token as challenge data~~ this isn't a serious application of cryptography, if it turns out to be a problem we'll fix it, but it definitely should not be easily possible to guess a SHA256 hash from the first 1/4 of it even if mathematically it might make it a bit easier
- ~~theme / make look nice??~~
- ~~add a spinner~~
- ~~add entry in example configuration~~
- ~~add documentation~~
Verification page originally based on https://github.com/LucienV1/powtect
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4043
Reviewed-by: tobi <tsmethurst@noreply.codeberg.org>
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
## Checklist
- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4081
Co-authored-by: Nicole Mikołajczyk <git@mkljczk.pl>
Co-committed-by: Nicole Mikołajczyk <git@mkljczk.pl>
Remove an unused import that was causing the testrig not to build properly.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4077
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
We need tags to do snapshots + releases properly! Another cheeky little difference from drone.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4069
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
# Description
This patch moves figures around in `admin/federation_modes.md` in order to make the text more approachable. Reading it, I found that I dwelled long on the chart, not thinking that there would be an easier to read explanation below, so I thought it'd make sense to swap the places. I also felt like the warning at the bottom was important enough that it'd better be up near the top of the section, highlighting the importance of understanding the explanation below.
I did not see a commit message style guide in project docs so I improvised based on recent commit messages
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [X] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [X] I/we have not leveraged AI to create the proposed changes.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4065
Co-authored-by: İ. Göktuğ Kayaalp <self@gkayaalp.com>
Co-committed-by: İ. Göktuğ Kayaalp <self@gkayaalp.com>
* [feature] Update attachment format, receive + send `focalPoint` prop + use it on the frontend
* whoops
* boop
* restore function signature of ExtractAttachments
* start work rewriting timeline cache type
* further work rewriting timeline caching
* more work integration new timeline code
* remove old code
* add local timeline, fix up merge conflicts
* remove old use of go-bytes
* implement new timeline code into more areas of codebase, pull in latest go-mangler, go-mutexes, go-structr
* remove old timeline package, add local timeline cache
* remove references to old timeline types that needed starting up in tests
* start adding page validation
* fix test-identified timeline cache package issues
* fix up more tests, fix missing required changes, etc
* add exclusion for test.out in gitignore
* clarify some things better in code comments
* tweak cache size limits
* fix list timeline cache fetching
* further list timeline fixes
* linter, ssssssssshhhhhhhhhhhh please
* fix linter hints
* reslice the output if it's beyond length of 'lim'
* remove old timeline initialization code, bump go-structr to v0.9.4
* continued from previous commit
* improved code comments
* don't allow multiple entries for BoostOfID values to prevent repeated boosts of same boosts
* finish writing more code comments
* some variable renaming, for ease of following
* change the way we update lo,hi paging values during timeline load
* improved code comments for updated / returned lo , hi paging values
* finish writing code comments for the StatusTimeline{} type itself
* fill in more code comments
* update go-structr version to latest with changed timeline unique indexing logic
* have a local and public timeline *per user*
* rewrite calls to public / local timeline calls
* remove the zero length check, as lo, hi values might still be set
* simplify timeline cache loading, fix lo/hi returns, fix timeline invalidation side-effects missing for some federated actions
* swap the lo, hi values 🤦
* add (now) missing slice reverse of tag timeline statuses when paging ASC
* remove local / public caches (is out of scope for this work), share more timeline code
* remove unnecessary change
* again, remove more unused code
* remove unused function to appease the linter
* move boost checking to prepare function
* fix use of timeline.lastOrder, fix incorrect range functions used
* remove comments for repeat code
* remove the boost logic from prepare function
* do a maximum of 5 loads, not 10
* add repeat boost filtering logic, update go-structr, general improvements
* more code comments
* add important note
* fix timeline tests now that timelines are returned in page order
* remove unused field
* add StatusTimeline{} tests
* add more status timeline tests
* start adding preloading support
* ensure repeat boosts are marked in preloaded entries
* share a bunch of the database load code in timeline cache, don't clear timelines on relationship change
* add logic to allow dynamic clear / preloading of timelines
* comment-out unused functions, but leave in place as we might end-up using them
* fix timeline preload state check
* much improved status timeline code comments
* more code comments, don't bother inserting statuses if timeline not preloaded
* shift around some logic to make sure things aren't accidentally left set
* finish writing code comments
* remove trim-after-insert behaviour
* fix-up some comments referring to old logic
* remove unsetting of lo, hi
* fix preload repeatBoost checking logic
* don't return on status filter errors, these are usually transient
* better concurrency safety in Clear() and Done()
* fix test broken due to addition of preloader
* fix repeatBoost logic that doesn't account for already-hidden repeatBoosts
* ensure edit submodels are dropped on cache insertion
* update code-comment to expand CAS accronym
* use a plus1hULID() instead of 24h
* remove unused functions
* add note that public / local timeline requester can be nil
* fix incorrect visibility filtering of tag timeline statuses
* ensure we filter home timeline statuses on local only
* some small re-orderings to confirm query params in correct places
* fix the local only home timeline filter func
* fix incorrect endpoint being registered for /token/{id}
* update the maximum page value for tokens endpoint to 100
* update the available tokens page options
* set a default limit of 25 to match the first available settings panel option
* ensure OnInvalidateToken() hook is called during token delete
* always include headerToken response if provided, because Chrome *sigh*
* wording
* Update internal/api/client/streaming/stream.go
Co-authored-by: Ilia Pozdnyakov <iliazeus@proton.me>
---------
Co-authored-by: Ilia Pozdnyakov <iliazeus@proton.me>
* [feature] add TOTP two-factor authentication (2FA)
* use byteutil.S2B to avoid allocations when comparing + generating password hashes
* don't bother with string conversion for consts
* use io.ReadFull
* use MustGenerateSecret for backup codes
* rename util functions
* [chore] Migrate accounts to new table, relax uniqueness constraint of actor url and collections
* fiddle with it! (that's what she said)
* remove unused cache fields
* sillyness
* fix tiny whoopsie
Most browsers just take the second src line and they're fine, but Tor
has trouble displaying the woff version on Linux. With two separate lines
it doesn't fall back correctly.
* [feature] Allow user to choose "gallery" style web layout
* find a bug and squish it up and all day long you'll have good luck
* just a sec
* [performance] reindex public timeline + tinker with query a bit
* fiddling
* should be good now
* last bit of finagling, i'm done now i prommy
* panic normally
* feat: Relax URL matching
Instead of only linkifying things with an explicit http or https scheme,
the xurls.Relaxed also matches links with known TLDs. This means that
text like 'banana.com' will also be matched, despite the missing
http/https scheme. This also works to linkify email addresses, which is
handy.
This should also ensure we catch links without a scheme for the purpose
of spam checking.
* [feature] Application creation + management via API + settings panel
* fix docs links
* add errnorows test
* use known application as shorter
* add comment about side effects
* add warning message when wazero compiler not supported, update supported platforms in README
* whoops don't return a reason string for arm64, since it should always be supported
* [feature] Parse content warning as HTML, serialize via API to plaintext
* tidy up some cruft
* whoops
* oops
* i'm da joker baybee
* clemency muy lorde
* rename some of the text functions for clarity
* jiggle the opts
* fiddle de deee
* hopefully the last test fix i ever have to do in my beautiful life
* Add ContentType to internal models
* Add ContentType to API models StatusSource and StatusEdit
* Add helpers to convert between API/internal StatusContentType
* Write status content type on create/edit
* Add migration
* Update API docs
go run github.com/go-swagger/go-swagger/cmd/swagger generate spec --scan-models --exclude-deps --output docs/api/swagger.yaml
* ensure ContentType is updated anywhere Text is
* Update docs, take care of TODOs
* Set ContentType in more places where Text is set
* We don't actually use ContentType on the API status model
* Update StatusSource test
* Remove unused helper function I copied
* Revert change to StatusContentType swagger annotation
I'm going to include this in a follow-on PR instead.
* Add test for updating content type in edits
* Return a value from processContentType instead of modifying the existing status
Fixes an issue that was caught by the test I just added - the recorded edit would be marked with the *new* content type instead of the old one, which is obviously bad
* Add test for handling of statuses with no stored content type
* repurpose an existing test status instead of adding a new one to avoid breaking other tests
* Add test to ensure newly created statuses always have content type saved
* Do include content type on status API model actually
This is mostly important when deleting and redrafting.
The comment on `apimodel.Status.Text` implies that it's not sent except in response to status deletion, but actually this doesn't seem to be the case; it also appears to be present in responses to creations and normal fetches and stuff. So I'm treating `ContentType` the same here.
* Update new tests to check content type on API statuses
* Check content type of API statuses in all tests where text is checked
* update other api tests with status content type field
* Add test ensuring text and content type are returned when deleting a status
* Convert processContentType to free function and remove unused parameter
* check for the correct value in the deletion test
* Be explicit about this test status having an empty content type
* Use omitempty consistently on API models
* clean up the final diff a bit
* one more swagger regen for the road
* Handle nil statuses in processContentType
* Don't pass processContentType the entire edit form, it doesn't need it
* Move processContentType to common.go and use for creation as well
* Remove unused parameters to ContentTypeToAPIContentType
* [bugfix] Fix app migration
* use temporary index during migration
* create temporary index for the migration
* include local = true in temporary index
* tweak migration a bit for SPEED
* fix refreshed additional media info being ignored when force flag already set
* also update to always iterate through all additional info fields
* make similar changes for emoji, even if not necessary, just to keep in-sync
The documentation explains that the release tag is in the format of `vX.Y.Z` for container images. This does not appear to be correct when looking at the image tags in dockerhub. It seems the `v` prefix has been dropped at some point, or was never in place.
* separate enum migrations into their own individual transactions
* pee poo
* some performance tweaks and adding more comments
* batch
---------
Co-authored-by: kim <grufwub@gmail.com>
* [bugfix] Drop status indices AFTER updating visibility
* rename to status vis indices just to indicate they're only used in the statuses hook func
---------
Co-authored-by: kim <grufwub@gmail.com>
* Implement backfilling statuses thru scheduled_at
* Forbid mentioning others in backfills
* Update error messages & codes
* Add new tests for backfilled statuses
* Test that backfilling doesn't timeline or notify
* Fix check for absence of notification
* Test that backfills do not cause federation
* Fix type of apimodel.StatusCreateRequest.ScheduledAt in tests
* Add config file switch and min date check
* updates the enum migration to perform a singular update for all values, using an SQL case statement
* fix logging
* fix code comment
* well i guess we'll get rid of the useful but unused function then, linter. fine, i see how it is!
* append to byte buffer instead of WriteString() to shut the linter up (i know you're reading this, linter)
* Stub out account's Group parameter
* Fix typo in Contributing documentation
* Update swagger and match style
* Update the swagger command to mimic test/swagger.sh
* Fix tests for new `group` param in Account model
* More test changes for new `group` param in Account
* Continuing test changes for `group` param stubbing
* Another round of `group` stubbing for tests
* this updates our support matrix to better reflect latest wazero changes (thanks @ncruces!)
* be more specific
* whoops, remove the BSD section being referenced for the linux builds
* fix markdown link, fix wording
* Web Push: add policy column to subscriptions
* Web Push: add policy to API
* Web Push: test notification policy
* go-fmt unrelated file (how did this get thru?)
webpush-go now supports sending `https://` as well as `mailto:` URLs for VAPID sub claims, so we can revert 464d920cfd now and save fetching the instance contact email or making up a dummy email if there wasn't one configured.
* Allow marks after NFC normalization
Includes regression test for the Tamil example from #3618
* Disallow just numbers + marks + underscore as hashtag
* remove type switch in Create() and instead move to FederatedCallbacks()
* add missing (my bad!) federating wrapped callbacks behaviour
* add missing license header 😇
* fix create flag test to use correct function
* weeeeenus
* update to latest activity
* update to use latest release tag of superseriousbusiness/activity
---------
Co-authored-by: kim <grufwub@gmail.com>
* Add login button to index page which reiterates info about clients
* bit of CSS fiddling, move apps from front page to login info
* fix indentation
---------
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
* Update push subscription API model to be Mastodon 4.0 compatible
* Add webpush-go dependency
# Conflicts:
# go.sum
* Single-row table for storing instance's VAPID key pair
* Generate VAPID key pair during startup
* Add VAPID public key to instance info API
* Return VAPID public key when registering an app
* Store Web Push subscriptions in DB
* Add Web Push sender (similar to email sender)
* Add no-op push senders to most processor tests
* Test Web Push notifications from workers
* Delete Web Push subscriptions when account is deleted
* Implement push subscription API
* Linter fixes
* Update Swagger
* Fix enum to int migration
* Fix GetVAPIDKeyPair
* Create web push subscriptions table with indexes
* Log Web Push server error messages
* Send instance URL as Web Push JWT subject
* Accept any 2xx code as a success
* Fix malformed VAPID sub claim
* Use packed notification flags
* Remove unused date columns
* Add notification type for update notifications
Not used yet
* Make GetVAPIDKeyPair idempotent
and remove PutVAPIDKeyPair
* Post-rebase fixes
* go mod tidy
* Special-case 400 errors other than 408/429
Most client errors should remove the subscription.
* Improve titles, trim body to reasonable length
* Disallow cleartext HTTP for Web Push servers
* Fix lint
* Remove redundant index on unique column
Also removes redundant unique and notnull tags on ID column since these are implied by pk
* Make realsender.go more readable
* Use Tobi's style for wrapping errors
* Restore treating all 5xx codes as temporary problems
* Always load target account settings
* Stub `policy` and `standard`
* webpush.Sender: take type converter as ctor param
* Move webpush.MockSender and noopSender into testrig
* alphabetical reordering
* keep a cache of activity IDs we have handled creates for
* reduce number of inbox forwarding create calls by partially implementing Exists()
* increase cache size, since all we're storing is string keys
* add seperate PunifyValidate() function for properly validating domain names when converting to punycode
* rename function, strip port from domain validation
* add migration to cleanup dropped status edits from previous bug, relinking with statuses
* don't use bun.Ident where not needed
* fix join statement
* fix query to work for both postgres and sqlite
* actually update by the currently set status ID field 🤦
* [bugfix] More permissive CSV parsing for perm subs, text parse fix
* wee
* change the way dry works, slightly
* me oh my, i'm just a little guy
* we're just normal men
* peepeepoopoo
* test domain perm subs
* swagger
* envparsing
* dries your wets
* start on docs
* finish up docs
* copy paste errors
* rename actions package
* rename force -> skipCache
* move obfuscate parse nearer to where err is checked
* make higherPrios a simple slice
* don't use receiver for permsFrom funcs
* add more context to error logs
* defer finished log
* use switch for permType instead of if/else
* thanks linter, love you <3
* validate csv headers before full read
* use bufio scanner
* update statuses table to replace updated_at column with edited_at
* code comment
* better code comments, fix setting of status + edit + mention + poll database times
* fix log to logf call
* fix status.EditIDs not being carried over in dereferencer.encrichStatus()
* move status.EditID setting into handleStatusEdit()
This will be either an mp1, mp2 or mp3 file. In practice it'll probably
be mp3, but this handles mp1 too for good measure. We don't advertise
audio/mp1 as a supported media type since best I can tell that was never
a MIME type that's been used.
This also changes the returned MIME-type for mp2 and mp3 to audio/mpeg,
to match what's expected and supported by most things nowadays.
Fixes: #3531
* ensure edited_at isn't set on boost wrapper statuses
* improve handling of remote status updated_at to fix previous cases
* formatting
* add remote status published / updated field validation checks, handle appropriately in handleStatusEdit()
* specifically allowed updated to be equal to published
* only check creation date change when an existing status
* start adding client support for making status edits and viewing history
* modify 'freshest' freshness window to be 5s, add typeutils test for status -> api edits
* only populate the status edits when specifically requested
* start adding some simple processor status edit tests
* add test editing status but adding a poll
* test edits appropriately adding poll expiry handlers
* finish adding status edit tests
* store both new and old revision emojis in status
* add code comment
* ensure the requester's account is populated before status edits
* add code comments for status edit tests
* update status edit form swagger comments
* remove unused function
* fix status source test
* add more code comments, move media description check back to media process in status create
* fix tests, add necessary form struct tag
* [chore] Stub /api/v1/announcements implementation
This implements the /api/v1/announcements endpoint by simply returning
an empty array. This indicates there are no instance announcements.
Some clients retrieve this endpoint and get surprised by a 404. It tends
to be harmless, but results in some unnecessary logging when trying to
debug other things.
* [fix] Forgot some swagger
* [fix] Fix swagger some more
* add support for extracting Updated field from Statusable implementers
* add support for status edits in the database, and update status dereferencer to handle them
* remove unused AdditionalInfo{}.CreatedAt
* remove unused AdditionalEmojiInfo{}.CreatedAt
* update new mention creation to use status.UpdatedAt
* remove mention.UpdatedAt, fixes related to NewULIDFromTime() change
* add migration to remove Mention{}.UpdatedAt field
* add migration to add the StatusEdit{} table
* start adding tests, add delete function for status edits
* add more of status edit migrations, fill in more of the necessary edit delete functionality
* remove unused function
* allow generating gotosocial compatible ulid via CLI with `go run ./cmd/gen-ulid`
* add StatusEdit{} test models
* fix new statusedits sql
* use model instead of table name
* actually remove the Mention.UpdatedAt field...
* fix tests now new models are added, add more status edit DB tests
* fix panic wording
* add test for deleting status edits
* don't automatically set `updated_at` field on updated statuses
* flesh out more of the dereferencer status edit tests, ensure updated at field set on outgoing AS statuses
* remove media_attachments.updated_at column
* fix up more tests, further complete the dereferencer status edit tests
* update more status serialization tests not expecting 'updated' AS property
* gah!! json serialization tests!!
* undo some gtscontext wrapping changes
* more serialization test fixing 🥲
* more test fixing, ensure the edit.status_id field is actually set 🤦
* fix status edit test
* grrr linter
* add edited_at field to apimodel status
* remove the choice of paging on the timeline public filtered test (otherwise it needs updating every time you add statuses ...)
* ensure that status.updated_at always fits chronologically
* fix more serialization tests ...
* add more code comments
* fix envparsing
* update swagger file
* properly handle media description changes during status edits
* slight formatting tweak
* code comment
Allow instance admins to add custom CSS that will affect
every page of their instance.
This is done with a new CustomCSS instance setting that
works pretty much exactly like the Users CustomCSS property.
This custom CSS is then requested for every page load.
User styles/themes take precedence over this CSS.
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Neither Semaphore nor Pinafore are under active development, but
Semaphore has archived its repository while Pinafore still gets
occasional minor maintenance.
Enafore has newer features, but it has accessibility bugs affecting
screen readers that prevent it from being recommended at this time.
* [chore] Bump tooling versions, bump go -> v1.23.0
* undo silly change
* sign
* bump go version in go.mod
* allow overflow in imaging
* goreleaser deprecation notices
* bump versions
* undo accidental rebase change
* update container versions to just use latest major version
* update swagger to our release with go1.23 fix
* update goreleaser to use our vendored swagger version
---------
Co-authored-by: kim <grufwub@gmail.com>
* convert statuses.visibility and notifications.notification_type columns from type string -> int for performance / space savings
* fix test trying to compare string to int
* fix instance count query using string literal instead of gtsmodel const type
* ensure a default value is always set
* also migrate the account settings and sin bin status tables
* initialize maps outside loops and place into singular enum mapping creation func
* use int16 for enum types
* update sinbinstatus creation to be from a snapshot at initial creation
* add snapshot of poll type at creation time
The maintainers messed with the v1.5.2 tag which causes Go checksum
validation problems as the Go module proxy saw and recorded the original
hash.
This updates to 1.5.3 which doesn't have the issue.
* [bugfix] post counters should not include direct messages #3504
The fix is relativly simple, it just adds a line to the relevant
function which excludes all private posts.
* Formating fix
* mb
* when appending log field only do so by minimal amount
* move slice utils to separate package to fix import cycle, add GrowJust() and AppendJust() functions
* fix GrowJust() not returning slice of same length
* improved xslices tests
* make AppendJust() test check for slice contents, fix AppendJust() final copying behaviour
* add a +1 with field growth to try minimise allocation for log 'msg' field
* determine mime-type to use during ffprobe evaluation stage, don't bother rechecking by file extension
* set mjpeg content-type
* fix up tests expecting differing default values
* .go files are now tagged with diff=go for better diffs
* go.sum is tagged with generated which suppresses the diff
* go.sum is tagged with merge=ours to reduce merge conflicts
go.mod isn't tagged with generated since it's useful to see it on
dependency bump PRs.
* [chore] Bump tooling versions, bump go -> v1.23.0
* undo silly change
* sign
* bump go version in go.mod
* allow overflow in imaging
* goreleaser deprecation notices
* [chore] Upgrade golangci-lint, ignore existing int overflow warnings
There is a new lint for unchecked int casts. Integer overflows are bad,
but the old code that triggers this lint seems to be perfectly fine.
Instead of disabling the lint entirely for new code as well, grandfather
in existing code.
* fix golangci-lint documentation link
* revert unrelated changes
* revert another unrelated change
* get rid of remaining nolint:gosec
* swagger updates
* apply review feedback
* fix wrong formatting specifier thing
* fix the linter for real
---------
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
* replicate issue
* update go-structr to v0.8.10 with internal linked-list fix, small tweaks to caching of interaction requests
* remove debug function
---------
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
* [docs] Don't run SQLite on networked storage
This updates our documentation to include warnings against running
SQLite on networked storage.
It also slightly reorganises and consolidates some admonitions on the
Getting Started page because it was getting a bit too busy with repeated
information.
* [docs] Reword a few things
* bump go-byteutil v1.2.0 -> v1.3.0 which has safer (as in long-term API consistency) byte <-> string conversions
* fix test relying on byteutil exported type no longer existing
* update go-storage dependency, for S3Storage manually call PutObject() so we can set content-type
* update calls to PutFile() to include the contentType
gh issue close $ISSUE --comment "This repository is a mirror. Please open issues on https://codeberg.org/superseriousbusiness/gotosocial." --reason "not planned"
gh issue lock $ISSUE
env:
GH_TOKEN:${{ secrets.GITHUB_TOKEN }}
ISSUE:${{ github.event.issue.html_url }}
- name:pr
if:${{ github.event.pull_request.id != '' }}
run:|
gh pr close $PULL_REQUEST --comment "This repository is a mirror. Please open PRs on https://codeberg.org/superseriousbusiness/gotosocial."
- "{{ if .IsSnapshot }}superseriousbusiness/{{ .ProjectName }}:snapshot-amd64{{ end }}"
- "{{ if not .IsSnapshot }}superseriousbusiness/{{ .ProjectName }}:{{ .Version }}-amd64{{ end }}"# Use version tag (eg., `0.19.0`, `0.19.0-rc1`) for proper releases and prereleases.
- "{{ if and (not .Prerelease) (not .IsSnapshot) }}superseriousbusiness/{{ .ProjectName }}:latest-amd64{{ end }}"# Only use `latest` for proper releases, not prereleases or snapshots.
- "{{ if .IsSnapshot }}superseriousbusiness/{{ .ProjectName }}:snapshot-amd64{{ end }}"# Only use `snapshot` for snapshot builds triggered by merge to main.
- "{{ if .IsSnapshot }}superseriousbusiness/{{ .ProjectName }}:snapshot-arm64v8{{ end }}"
- "{{ if not .IsSnapshot }}superseriousbusiness/{{ .ProjectName }}:{{ .Version }}-arm64v8{{ end }}"# Use version tag (eg., `0.19.0`, `0.19.0-rc1`) for proper releases and prereleases.
- "{{ if and (not .Prerelease) (not .IsSnapshot) }}superseriousbusiness/{{ .ProjectName }}:latest-arm64v8{{ end }}"# Only use `latest` for proper releases, not prereleases or snapshots.
- "{{ if .IsSnapshot }}superseriousbusiness/{{ .ProjectName }}:snapshot-arm64v8{{ end }}"# Only use `snapshot` for snapshot builds triggered by merge to main.
name_template:"{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 \"v1\") }}{{ .Amd64 }}{{ end }}"
# NOWASM BUILD
-
id:gotosocial_nowasm
builds:
- gotosocial_nowasm
files:
# standard release files
- LICENSE
- README.md
- CHANGELOG*
# web stuff minus source
- web/assets
- web/template
# example config files
- example/config.yaml
- example/gotosocial.service
name_template:"{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 \"v1\") }}{{ .Amd64 }}{{ end }}_nowasm"
Please read the migration notes carefully for instructions on how to upgrade to this version.
## Release highlights
- Pee pee
- Poo poo
- Wee wee
## Migration notes
### Upgrading
To upgrade to {{ .Tag }} from a previous release:
#### Binary/tar
1. Stop GoToSocial.
2. **Back up your database!** If you're running on SQLite, this is as simple as copying your `sqlite.db` file, eg., `cp sqlite.db sqlite.db.backup`. On Postgres you can do this with [pg_dump](https://www.postgresql.org/docs/current/backup-dump.html).
3. Download and untar the new release, **including the web assets and html templates**, not just the binary.
4. Edit your config.yaml file if necessary (see below).
5. Start GoToSocial.
6. Wait patiently for any migrations to run, **do not interrupt migrations or you could leave your db in a broken state and will have to restore from backup**!
7. Enjoy your updated instance.
#### Docker
1. Stop GoToSocial.
2. **Back up your database!** If you're running on SQLite, this is as simple as copying your `sqlite.db` file, eg., `cp sqlite.db sqlite.db.backup`. On Postgres you can do this with [pg_dump](https://www.postgresql.org/docs/current/backup-dump.html).
3. Pull the new docker container with `docker pull docker.io/superseriousbusiness/gotosocial:{{ .Version }}` or `docker pull docker.io/superseriousbusiness/gotosocial:latest` if this is a stable release and not a release candidate.
4. Edit your config.yaml file or environment variables if necessary (see below).
5. Start GoToSocial.
6. Wait patiently for any migrations to run, **do not interrupt migrations or you could leave your db in a broken state and will have to restore from backup**!
7. Enjoy your updated instance.
### config.yaml
The configuration file has changed since the previous release.
- Changed `pee pee` to `poo poo`.
- Changed `wee wee` to `more wee wee`.
You can see a diff of the config file here:https://codeberg.org/superseriousbusiness/gotosocial/compare/{{ .PreviousTag }}...{{ .Tag }}#diff-c071e03510b2c57e193a44503fd9528a785f0f411497cc75841a9f8d0b1ac622
### Database Migrations
⚠️⚠️⚠️
This release may contain database migrations which will run the first time you start up this new version.
Be sure not to interrupt this migration process.
This will take anywhere between a couple seconds and ten minutes or more (on slower hardware).
**Pleasebe patient!**
⚠️⚠️⚠️
### Which release archive/container should I use?
GoToSocial releases binary builds for 64-bit Linux, FreeBSD, and NetBSD operating systems. We also release Docker builds for 64-bit Linux.
| OS | Architecture | Support level | Binary archive | Docker |
| Linux | x86-64/AMD64 (64-bit) | 🟢 Full | [linux_amd64.tar.gz](https://codeberg.org/superseriousbusiness/gotosocial/releases/download/{{ .Tag }}/gotosocial_{{ .Version }}_linux_amd64.tar.gz) | `docker.io/superseriousbusiness/gotosocial:{{ .Version }}` |
| Linux | Armv8/ARM64 (64-bit) | 🟢 Full | [linux_arm64.tar.gz](https://codeberg.org/superseriousbusiness/gotosocial/releases/download/{{ .Tag }}/gotosocial_{{ .Version }}_linux_arm64.tar.gz) | `docker.io/superseriousbusiness/gotosocial:{{ .Version }}` |
| FreeBSD | x86-64/AMD64 (64-bit) | 🟢 Full | [freebsd_amd64.tar.gz](https://codeberg.org/superseriousbusiness/gotosocial/releases/download/{{ .Tag }}/gotosocial_{{ .Version }}_freebsd_amd64.tar.gz) | Not provided |
| FreeBSD | Armv8/ARM64 (64-bit) | 🟢 Full | [freebsd_arm64.tar.gz](https://codeberg.org/superseriousbusiness/gotosocial/releases/download/{{ .Tag }}/gotosocial_{{ .Version }}_freebsd_arm64.tar.gz) | Not provided |
| NetBSD | x86-64/AMD64 (64-bit) | 🟢 Full | [netbsd_amd64.tar.gz](https://codeberg.org/superseriousbusiness/gotosocial/releases/download/{{ .Tag }}/gotosocial_{{ .Version }}_netbsd_amd64.tar.gz) | Not provided |
| NetBSD | Armv8/ARM64 (64-bit) | 🟢 Full | [netbsd_arm64.tar.gz](https://codeberg.org/superseriousbusiness/gotosocial/releases/download/{{ .Tag }}/gotosocial_{{ .Version }}_netbsd_arm64.tar.gz) | Not provided |
#### `nowasm`
For your convenience, we also provide **UNSUPPORTED, EXPERIMENTAL BUILDS**, created using the `nowasm` tag, in the downloads list below. There is no Docker build for `nowasm`.
GoToSocial releases built with `nowasm` use the Go-native, modernc version of SQLite instead of the WASM one, and will use *on-system ffmpeg and ffprobe binaries* for media processing.
Using a `nowasm` build is currently the only way to run GoToSocial on a 32-bit system.
For more information on running a `nowasm` build, see the [nowasm](https://docs.gotosocial.org/en/latest/advanced/builds/nowasm/) documentation page.
- [What if something goes wrong?](#what-if-something-goes-wrong)
- [CI/CD configuration](#ci-cd-configuration)
- [Other Useful Stuff](#other-useful-stuff)
- [Running migrations on a Postgres DB backup locally](#running-migrations-on-a-postgres-db-backup-locally)
## Introduction
@ -41,11 +42,11 @@ This document contains important information that will help you to write a succe
## Bug reports and feature requests
Currently, we use Github's issue system for tracking bug reports and feature requests.
Currently, we use Codeberg's issue system for tracking bug reports and feature requests.
You can view all open issues [here](https://github.com/superseriousbusiness/gotosocial/issues "The Github Issues page for GoToSocial").
You can view all open issues [here](https://codeberg.org/superseriousbusiness/gotosocial/issues "The Codeberg Issues page for GoToSocial").
Before opening a new issue, whether bug or feature request, **please search carefully through both open and closed issues to make sure it hasn't been addressed already**. You can use Github's keyword issue search for this. If your issue is a duplicate of an existing issue, it will be closed.
Before opening a new issue, whether bug or feature request, **please search carefully through both open and closed issues to make sure it hasn't been addressed already**. You can use Codeberg's keyword issue search for this. If your issue is a duplicate of an existing issue, it will be closed.
Before you open a feature request issue, please consider the following:
@ -99,7 +100,7 @@ If you see something in the documentation that's missing, wrong, or unclear, fee
We support a [Conda](https://docs.conda.io/en/latest/)-based workflow for hacking, building & publishing the documentation. Here's how you can get started locally:
* Create your conda environment: `conda env create -f ./docs/environment.yml`
* Activate the environment: `conda activate gotosocial-docs`
* Serve locally: `mkdocs serve`
@ -122,26 +123,22 @@ Beware that `conda env export` will add a `prefix` entry to the environment.yml
### Golang forking quirks
One of the quirks of Golang is that it relies on the source management path being the same as the one used within `go.mod` and in package imports within individual Go files. This makes working with forks a bit awkward.
Let's say you fork GoToSocial to `github.com/yourgithubname/gotosocial`, and then clone that repository to `~/go/src/github.com/yourgithubname/gotosocial`. You will probably run into errors trying to run tests or build, so you might change your `go.mod` file so that the module is called `github.com/yourgithubname/gotosocial` instead of `github.com/superseriousbusiness/gotosocial`. But then this breaks all the imports within the project. Nightmare! So now you have to go through the source files and painstakingly replace `github.com/superseriousbusiness/gotosocial` with `github.com/yourgithubname/gotosocial`. This works OK, but when you decide to make a pull request against the original repo, all the changed paths are included! Argh!
The correct solution to this is to fork, then clone the upstream repository, then set `origin` of the upstream repository to that of your fork.
One of the quirks of Golang is that it relies on the source management path being the same as the one used within `go.mod` and in package imports within individual Go files. This makes working with forks a bit awkward. The solution to this is to fork, then clone the upstream repository, then set `origin` of the upstream repository to that of your fork.
See [this blog post](https://blog.sgmansfield.com/2016/06/working-with-forks-in-go/) for more details.
In case this post disappears, here are the steps (slightly modified):
>
> Fork the repository on GitHub or set up whatever other remote git repo you will be using. In this case, I would go to GitHub and fork the repository.
> Fork the repository on Codeberg or set up whatever other remote git repo you will be using. In this case, I would go to Codeberg and fork the repository.
Be sure to run `git fetch` before building the project for the first time.
@ -158,9 +155,9 @@ Be sure to run `git fetch` before building the project for the first time.
#### Binary
To get started, you first need to have Go installed. GtS is currently using Go 1.21, so you should take that too. See [here](https://golang.org/doc/install) for installation instructions.
To get started, you first need to have Go installed. Check the top of the `go.mod` file to see which version of Go you need to install, and see [here](https://golang.org/doc/install) for installation instructions.
Once you've got go installed, clone this repository into your Go path. Normally, this should be `~/go/src/github.com/superseriousbusiness/gotosocial`.
Once you've got Go installed, clone this repository into your Go path. Normally, this should be `~/go/src/code.superseriousbusiness.org/gotosocial`.
Once you've installed the prerequisites, you can try building the project: `./scripts/build.sh`. This will build the `gotosocial` binary.
@ -176,7 +173,7 @@ nodemon -e go --signal SIGTERM --exec "go run ./cmd/gotosocial --host localhost
#### Docker
For both of the below methods, you need to have [Docker buildx](https://docs.docker.com/buildx/working-with-buildx/) installed.
For both of the below methods, you need to have [Docker buildx](https://docs.docker.com/build/concepts/overview/#buildx) installed.
##### With GoReleaser
@ -188,21 +185,19 @@ Normally, these processes are handled by Drone (see CI/CD above). However, you c
To do this, first [install GoReleaser](https://goreleaser.com/install/).
Then install GoSwagger as described in [the Swagger section](#updating-swagger-docs).
Then install Node and Yarn as described in [Stylesheet / Web dev](#stylesheet--web-dev).
Then install Node and Yarn as described in [Stylesheet / Web dev](#stylesheet-web-dev).
Finally, to create a snapshot build, do:
```bash
goreleaser --rm-dist --snapshot
goreleaser release --clean --snapshot
```
If all goes according to plan, you should now have a number of multiple-architecture binaries and tars inside the `./dist` folder, and snapshot Docker images should be built (check your terminal output for version).
##### Manually
If you prefer a simple approach to building a Docker container, with fewer dependencies (go-swagger, Node, Yarn), you can also just build in the following way:
If you prefer a simple approach to building a Docker container, with fewer dependencies (Node, Yarn), you can also just build in the following way:
@ -210,6 +205,8 @@ If you prefer a simple approach to building a Docker container, with fewer depen
The above command first builds the `gotosocial` binary, then invokes Docker buildx to build the container image.
If you get an error while doing the build that looks like `"/web/assets/swagger.yaml": not found`, then you need to (re)generate the Swagger docs once, see [Updating Swagger docs](#updating-swagger-docs) for the command.
If you want to build a docker image for a different CPU architecture without setting up buildx (for example for ARMv7 aka 32-bit ARM), first modify the Dockerfile by adding the following lines to the top (but don't commit this!):
```dockerfile
@ -385,7 +382,7 @@ We use [golangci-lint](https://golangci-lint.run/) for linting, which allows us
If you make a PR that doesn't pass the linter, it will be rejected. As such, it's good practice to run the linter locally before pushing or opening a PR.
To do this, first install the linter following the instructions [here](https://golangci-lint.run/usage/install/#local-installation).
To do this, first install the linter following the instructions [here](https://golangci-lint.run/welcome/install/).
Then, you can run the linter with:
@ -397,13 +394,13 @@ If there's no output, great! It passed :)
### Testing
GoToSocial provides a [testrig](https://github.com/superseriousbusiness/gotosocial/tree/main/testrig) with a number of mock packages you can use in integration tests.
GoToSocial provides a [testrig](https://codeberg.org/superseriousbusiness/gotosocial/tree/main/testrig) with a number of mock packages you can use in integration tests.
One thing that *isn't* mocked is the Database interface because it's just easier to use an in-memory SQLite database than to mock everything out.
#### Standalone Testrig with Semaphore
#### Standalone Testrig with Pinafore
You can launch a testrig as a standalone server running at localhost, which you can connect to using something like [Semaphore](https://github.com/NickColley/semaphore/).
You can launch a testrig as a standalone server running at localhost, which you can connect to using something like [Pinafore](https://github.com/nolanlawson/pinafore/).
To do this, first build the gotosocial binary with `DEBUG=1 ./scripts/build.sh`.
@ -413,14 +410,14 @@ Then, launch the testrig with the `DEBUG` environment variable set by invoking t
DEBUG=1 ./gotosocial testrig start
```
To run Semaphore locally in dev mode, first clone the [Semaphore](https://github.com/NickColley/semaphore/) repository, and then run the following commands in the cloned directory:
To run Pinafore locally in dev mode, first clone the [Pinafore](https://github.com/nolanlawson/pinafore/) repository, and then run the following commands in the cloned directory:
```bash
yarn # install dependencies
yarn run dev
```
The Semaphore instance will start running on `localhost:4002`.
The Pinafore instance will start running on `localhost:4002`.
To connect to the testrig, navigate to `http://localhost:4002` and enter your instance name as `localhost:8080`.
@ -428,10 +425,35 @@ At the login screen, enter the email address `zork@example.org` and password `pa
Note the following constraints:
- Since the testrig uses an in-memory database, the database will be destroyed when the testrig is stopped.
- If you stop the testrig and start it again, any tokens or applications you created during your tests will also be removed. As such, you need to log out and in again every time you stop/start the rig.
- Since the testrig uses an in-memory database by default, the database will be destroyed when the testrig is stopped.
- If you stop the testrig and start it again, by default any tokens or applications you created during your tests will also be removed. As such, you need to log out and in again every time you stop/start the rig.
- The testrig does not make any actual external HTTP calls, so federation will not work from a testrig.
##### Configuring the Standalone Testrig
By default the standalone testrig uses an in-memory SQLite database, which is filled with test data when starting up, and is cleared when shutting down, but you can tweak this (and a few other settings) with environment variables:
- `GTS_LOG_LEVEL` - you can set this to `trace` if you want to see all DB queries.
- `GTS_TESTRIG_SKIP_DB_SETUP` - set this to any value to skip the creation of tables and population of test data when the testrig starts.
- `GTS_TESTRIG_SKIP_DB_TEARDOWN` - set this to any value to skip the deletion of tables and test data when the testrig stops.
- `GTS_STORAGE_BACKEND` - this uses in-memory storage by default, but you can set this to `s3` to use a locally-running Minio etc for testing.
- `GTS_DB_TYPE` - you can change this to `postgres` to test against a locally-running Postgres intance.
- `GTS_DB_ADDRESS` - this is set to `:memory:` by default. You can change this to use an sqlite.db file somewhere, or set it to a Postgres address.
- `GTS_DB_PORT`, `GTS_DB_USER`, `GTS_DB_PASSWORD`, `GTS_DB_DATABASE`, `GTS_DB_TLS_MODE`, `GTS_DB_TLS_CA_CERT` - you can set these if you change `GTS_DB_ADDRESS` to `postgres` and don't use `GTS_DB_POSTGRES_CONNECTION_STRING`.
- `GTS_DB_POSTGRES_CONNECTION_STRING` - use this to provide a Postgres connection string if you don't want to set all the db env variables mentioned in the previous point.
Using these variables you can also (albeit awkwardly) test migrations from one schema to another.
For example, to test SQLite migrations:
1. Switch to main branch.
2. Build the debug binary, and then start the testrig with `DEBUG=1 GTS_LOG_LEVEL=trace GTS_DB_ADDRESS=./sqlite.test.db GTS_TESTRIG_SKIP_DB_TEARDOWN=1 ./gotosocial testrig start`. This instructs the testrig to use trace logging, use an actual file for the SQLite db, and to skip tearing it down when finished.
3. Stop the testrig.
4. The file `sqlite.test.db` now contains the schema and test models from the main branch.
5. Switch to the branch with the migration you want to test.
6. Build the debug binary, and then start the testrig with `DEBUG=1 GTS_LOG_LEVEL=trace GTS_DB_ADDRESS=./sqlite.test.db GTS_TESTRIG_SKIP_DB_SETUP=1 ./gotosocial testrig start`. This instructs the testrig to use trace logging, and to use the already-populated sqlite.test.db file.
7. You should see logging for migrations.
#### Running automated tests
Tests can be run against both SQLite and Postgres.
@ -484,65 +506,59 @@ You'll additionally need functioning DNS for your two instance names, which you
GoToSocial uses [go-swagger](https://goswagger.io) to generate Swagger API documentation from code annotations.
You can install go-swagger following the instructions [here](https://goswagger.io/install.html).
If you change Swagger annotations on any of the API paths, you can generate a new Swagger file at `./docs/api/swagger.yaml` by running:
If you change Swagger annotations on any of the API paths, you can generate a new Swagger file at `./docs/api/swagger.yaml`, and copy that file to web assets, by running:
You shouldn't need to install go-swagger to run this command, as it's already included in the `vendor` folder.
### CI/CD configuration
GoToSocial uses [Drone](https://www.drone.io/) for CI/CD tasks like running tests, linting, and building Docker containers.
GoToSocial uses [Woodpecker CI](https://woodpecker-ci.org/) for CI/CD tasks like running tests, linting, and building Docker containers.
These runs are integrated with GitHub, and will be run on opening a pull request or merging into main.
These runs are integrated with Codeberg, and will be run on opening a pull request or merging into main.
The Drone instance for GoToSocial is [here](https://drone.superseriousbusiness.org/superseriousbusiness/gotosocial).
The `woodpecker` pipeline files are in the `.woodpecker` directory of this repository — these define how and when Woodpecker should run.
The `drone.yml` file is [here](./.drone.yml) — this defines how and when Drone should run. Documentation for Drone is [here](https://docs.drone.io/).
The Woodpecker instance for GoToSocial is [here](https://woodpecker.superseriousbusiness.org/repos/2).
It is worth noting that the `drone.yml` file must be signed by the Drone admin account to be considered valid. This must be done every time the file is changed. This is to prevent tampering and hijacking of the Drone instance. See [here](https://docs.drone.io/signature/).
Documentation for Woodpecker is [here](https://woodpecker-ci.org/docs/intro).
To sign the file, first install and setup the [drone cli tool](https://docs.drone.io/cli/install/). Then, run:
## Other Useful Stuff
Various bits and bobs.
### Running migrations on a Postgres DB backup locally
It may be useful when testing or debugging migrations to be able to run them against a copy of a real instance's Postgres database locally.
Basic steps for this:
First dump the Postgres database on the remote machine, and copy the dump over to your development machine.
Now create a local Postgres container and mount the dump into it with, for example:
Now, with that out of the way, here's our Checklist.
With the Postgres container still running, run GoToSocial and point it towards the container. Use the appropriate `GTS_HOST` (and `GTS_ACCOUNT_DOMAIN`) values for the instance you dumped:
- Do the assets have to be rebuilt and committed to the repository.
- Do the swagger docs have to be rebuilt?
On the project management side:
- Are there any issues that have to be moved to a different milestone?
- Are there any things on the [Roadmap](./ROADMAP.md) that can be ticked off?
Once we're happy with our Checklist, we can create the tag, and push it.
And the rest [is automation](./.drone.yml).
We can now head to GitHub, and add some personality to the release notes.
Finally, we make announcements on the all our channels that the release is out!
#### What if something goes wrong?
Sometimes things go awry.
We release a buggy release, we forgot something something important.
If the release is so bad that it's unusable or dangerous! to a great part of our user-base, we can pull.
That is: Delete the tag.
Either way, once we've resolved the issue, we just start from the top of this list again. Version numbers are cheap. It's cheap to burn them.
When you're done messing around, don't forget to remove any containers that you started up, and remove any lingering volumes with `docker volume prune`, else you might end up filling your disk with unused temporary volumes.
**Update regarding corporate sponsors: we are open to sponsorship arrangements with organizations that align with our values; see the conditions below**
GoToSocial is an [ActivityPub](https://activitypub.rocks/) social network server, written in Golang.
🏳️🌈 GoToSocial is an [ActivityPub](https://activitypub.rocks/) social network server, written in Golang. 🏳️⚧️
With GoToSocial, you can keep in touch with your friends, post, read, and share images and articles. All without being tracked or advertised to!
**GoToSocial is still [BETA SOFTWARE](https://en.wikipedia.org/wiki/Software_release_life_cycle#Beta)**. It is already deployable and useable, and it federates cleanly with many other Fediverse servers (not yet all). However, many things are not yet implemented, and there are plenty of bugs! We left alpha stage around September/October 2024, and we intend to exit beta some time around 2026.
Documentation is at [docs.gotosocial.org](https://docs.gotosocial.org). You can skip straight to the API documentation [here](https://docs.gotosocial.org/en/latest/api/swagger/).
To build from source, check the [CONTRIBUTING.md](https://github.com/superseriousbusiness/gotosocial/blob/main/CONTRIBUTING.md) file.
To build from source, check the [CONTRIBUTING.md](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md) file.
Here's a screenshot of the instance landing page!
Here's a screenshot of the instance landing page! Check out the project's [official account](https://gts.superseriousbusiness.org/@gotosocial) running on GoToSocial.


<!--overview-end-->
## Table of Contents <!-- omit in toc -->
@ -36,16 +36,22 @@ Here's a screenshot of the instance landing page!
@ -55,7 +61,7 @@ Here's a screenshot of the instance landing page!
- [Image Attribution and Licensing](#image-attribution-and-licensing)
- [Team](#team)
- [Special Thanks](#special-thanks)
- [Sponsorship + Funding](#sponsorship--funding)
- [Sponsorship + Funding](#sponsorship-funding)
- [Crowdfunding](#crowdfunding)
- [Corporate Sponsorship](#corporate-sponsorship)
- [NLnet](#nlnet)
@ -68,7 +74,7 @@ GoToSocial provides a lightweight, customizable, and safety-focused entryway int
If you've ever used something like Twitter or Tumblr (or even Myspace!) GoToSocial will probably feel familiar to you: You can follow people and have followers, you make posts which people can favourite and reply to and share, and you scroll through posts from people you follow using a timeline. You can write long posts or short posts, or just post images, it's up to you. You can also, of course, block people or otherwise limit interactions that you don't want by posting just to your friends.


**GoToSocial does NOT use recommendation algorithms or collect data about you to suggest content or 'improve your experience'**. The timeline is chronological: whatever you see at the top of your timeline is there because it's *just been posted*, not because it's been selected as interesting (or controversial) based on your personal profile.
@ -80,7 +86,7 @@ GoToSocial doesn't claim to be *better* than any other application, but it offer
Because GoToSocial uses [ActivityPub](https://activitypub.rocks/), you can hang out not just with people on your home server, but with people all over the [Fediverse](https://en.wikipedia.org/wiki/Fediverse), seamlessly.
Federation means that your home server is part of a network of servers all over the world that all communicate using the same protocol. Your data is no longer centralized on one company's servers, but resides on your own server and is shared — as you see fit — across a resilient web of servers run by other people.
@ -96,7 +102,7 @@ It began as a solo project, and then picked up steam as more developers became i
We made our first Alpha release in November 2021. We left Alpha and entered Beta in September/October 2024.
For a detailed view on what's implemented and what's not, and progress made towards [stable release](https://en.wikipedia.org/wiki/Software_release_life_cycle#Stable_release), please see [the roadmap document](https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md).
For a detailed view on what's implemented and what's not, and progress made towards [stable release](https://en.wikipedia.org/wiki/Software_release_life_cycle#Stable_release), please see [the roadmap document](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/ROADMAP.md).
---
@ -109,7 +115,7 @@ The Mastodon API has become the de facto standard for client communication with
Though most apps that implement the Mastodon API should work, GoToSocial is tested and works reliably with beautiful apps like:
* [Tusky](https://tusky.app/) for Android
* [Semaphore](https://semaphore.social/) in the browser
* [Pinafore](https://pinafore.social/) in the browser
* [Feditext](https://github.com/feditext/feditext) (beta) on iOS, iPadOS and macOS
If you've used Mastodon with a third-party app before, you'll find using GoToSocial a breeze.
@ -124,11 +130,11 @@ GoToSocial offers public, unlisted/unlocked, followers-only, and direct posts (s
GoToSocial lets you choose who can reply to your posts, via [interaction policies](https://docs.gotosocial.org/en/latest/user_guide/settings/#default-interaction-policies). You can choose to let anyone reply to your posts, let only your friends reply, and more.
Sometimes you only want to talk to people you share an instance with. GoToSocial supports this via local-only posting, which ensures that your post stays on your instance only. (Local-only posting is currently dependent on client support.)
Sometimes you only want to talk to people you share an instance with. GoToSocial supports this via local-only posting, which ensures that your post stays on your instance only, even if it gets boosted. They also do not show up in the web interface, and are not accessible publicly via URL. (Local-only posting is currently dependent on client support.)
### RSS feed
@ -138,7 +144,7 @@ GoToSocial lets you opt-in to exposing your profile as an RSS feed, so that peop
With GoToSocial, you can write posts using the popular, easy-to-use Markdown markup language, which lets you produce rich HTML posts with support for blockquotes, syntax-highlighted code blocks, lists, inline links, and more.
GoToSocial uses only about 250-350MiB of RAM, and requires very little CPU power, so it plays nice with single-board computers, old laptops and tiny $5/month VPSes.


No external dependencies apart from a database (or just use SQLite!).
@ -217,10 +247,12 @@ Simply download the binary + assets (or Docker container), tweak your configurat
### Safety + security features
- Built-in, automatic support for secure HTTPS with [Let's Encrypt](https://letsencrypt.org/).
- Strict privacy enforcement for posts and strict blocking logic.
- Import and export allow lists and deny lists. Subscribe to community-created block lists (think Ad blocker, but for federation!) (feature still in progress).
- Strict privacy enforcement for posts, and strict blocking logic.
- [Choose the visibility of posts on the web view of your profile](https://docs.gotosocial.org/en/latest/user_guide/settings/#visibility-level-of-posts-to-show-on-your-profile).
- [Import, export](https://docs.gotosocial.org/en/latest/admin/settings/#importexport), and [subscribe](https://docs.gotosocial.org/en/latest/admin/domain_permission_subscriptions) to community-created domain allow and domain block lists.
- HTTP signature authentication: GoToSocial requires [HTTP Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12) when sending and receiving messages, to ensure that your messages can't be tampered with and your identity can't be forged.
- Built-in, automatic support for secure HTTPS with [Let's Encrypt](https://letsencrypt.org/).
- Support for two-factor authentication via time-based one-time passwords (Google authenticator, LastPass authenticator, etc).
### Various federation modes
@ -246,23 +278,85 @@ On top of this API, web developers are encouraged to build any front-end impleme
---
## Known Issues
## Alternatives to GoToSocial
Since GoToSocial is still in beta, there are plenty of bugs. We use [GitHub issues](https://github.com/superseriousbusiness/gotosocial/issues?q=is%3Aissue+is%3Aopen+label%3Abug) to track these.
Don't like GtS but still want to use the fediverse? Like GtS but prefer not to use beta software? There are lots of alternatives that might suit you better! Here are some that we know work well (alphabetical order):
Since every ActivityPub server implementation has a slightly different interpretation of the protocol, some servers don't quite federate properly with GoToSocial yet. We're tracking these issues [in this project](https://github.com/superseriousbusiness/gotosocial/projects/4). Eventually, we want to make sure that any implementation that can federate nicely with Mastodon should also be able to federate with GoToSocial.
- [Akkoma](https://akkoma.social/): Full-featured ActivityPub microblogging with emoji reacts and quote posts (Elixir).
- [Honk](https://humungus.tedunangst.com/r/honk/m/activitypub.7): Minimalist, opinionated microblogging with "No likes, no faves, no polls, no stars, no claps, no counts." (Go).
- [Iceshrimp.net](https://iceshrimp.dev/iceshrimp/Iceshrimp.NET): rewrite of Iceshrimp from the ground up (.Net).
- [Snac2](https://codeberg.org/grunfink/snac2): Simple, minimalistic instance with very low system requirements (portable C).
---
## Getting Started
## Known Issues
Check our [releases page](https://github.com/superseriousbusiness/gotosocial/releases) and our [getting started](https://docs.gotosocial.org/en/latest/getting_started/) documentation.
Since GoToSocial is still in beta, there are plenty of bugs. We use [Codeberg issues](https://codeberg.org/superseriousbusiness/gotosocial/issues?labels=378161) to track these.
Since every ActivityPub server implementation has a slightly different interpretation of the protocol, some servers don't quite federate properly with GoToSocial yet. We're tracking these issues [with the federation label](https://codeberg.org/superseriousbusiness/gotosocial/issues?labels=378188). Eventually, we want to make sure that any implementation that can federate nicely with Mastodon should also be able to federate with GoToSocial.
---
## Installing GoToSocial
Check our [getting started](https://docs.gotosocial.org/en/latest/getting_started/) documentation! And have a peruse of our [releases page](https://codeberg.org/superseriousbusiness/gotosocial/releases).
<!--releases-start-->
### Supported Platforms
While we try to support a reasonable number of architectures and operating systems, it's not always possible to support a given platform due to library constraints or performance issues.
Platforms that we don't officially support *may* still work, but we can't test or guarantee performance or stability.
This is the current status of support offered by GoToSocial for different platforms (if something is unlisted it means we haven't checked yet so we don't know):
| OS | Architecture | Support level | Binary archive | Docker container |
| OpenBSD | Any | 🔴 None<sup>[4](#openbsd)</sup> | No | No |
#### 64-bit
Notes on 64-bit CPU feature requirements:
- x86_64 requires the [x86-64-v2](https://en.wikipedia.org/wiki/X86-64-v2) level instruction sets. (CPUs manufactured after ~2010)
- ARM64 requires no specific features, ARMv8 CPUs (and later) have all required features.
If any of the above features are missing, performance of media processing (and possibly, SQLite) will suffer. In these situations, you may have some success building a binary yourself with the totally **unsupported, experimental** [nowasm](https://docs.gotosocial.org/en/latest/advanced/builds/nowasm/) tag.
#### BSDs
Mostly works, just [a few things to keep in mind](https://github.com/ncruces/go-sqlite3/wiki/Support-matrix) with WASM SQLite; check release notes carefully when installing on NetBSD or FreeBSD. If running with Postgres you should have no issues.
#### 32-bit
GtS doesn't work well on 32-bit systems like i386, or Armv6/v7, mainly due to performance of media decoding.
We don't recommend running GtS on 32-bit, but you may have some success either turning off remote media processing altogether, or building a binary yourself with the totally **unsupported, experimental** [nowasm](https://docs.gotosocial.org/en/latest/advanced/builds/nowasm/) tag.
For more guidance, check release notes when trying to install on 32-bit.
#### OpenBSD
Marked as unsupported due to performance issues (no WASM compiler, high memory usage when idle, crashes while processing media).
While we don't support running GtS on OpenBSD, you may have some success building a binary yourself with the totally **unsupported, experimental** [nowasm](https://docs.gotosocial.org/en/latest/advanced/builds/nowasm/) tag.
### Stable Releases
We package our stable releases for both binary builds and Docker containers, so that you don't have to build from source yourself.
The Docker image `superseriousbusiness/gotosocial:latest` will always correspond to the latest stable release. Since this tag is overwritten frequently, you may want to use Docker CLI flag `--pull always` to ensure that you always have the most up-to-date image every time you run using this tag. Alternatively, run `docker pull superseriousbusiness/gotosocial:latest` manually just before use.
The Docker image `docker.io/superseriousbusiness/gotosocial:latest` will always correspond to the latest stable release. Since this tag is overwritten frequently, you may want to use Docker CLI flag `--pull always` to ensure that you always have the most up-to-date image every time you run using this tag. Alternatively, run `docker pull docker.io/superseriousbusiness/gotosocial:latest` manually just before use.
### Snapshot Releases
@ -272,17 +366,17 @@ Please be warned that you do so at your own risk! We try to keep main working pr
#### Docker
To run from main using Docker, use the `snapshot` Docker tag. The Docker image `superseriousbusiness/gotosocial:snapshot` will always correspond to the latest commit on main. Since this tag is overwritten frequently, you may want to use Docker CLI flag `--pull always` to ensure that you always have the most up-to-date image every time you run using this tag. Alternatively, run `docker pull superseriousbusiness/gotosocial:snapshot` manually just before use.
To run from main using Docker, use the `snapshot` Docker tag. The Docker image `docker.io/superseriousbusiness/gotosocial:snapshot` will always correspond to the latest commit on main that involves changes to Go code or web assets/source. Since this tag is overwritten frequently, you may want to use Docker CLI flag `--pull always` to ensure that you always have the most up-to-date image every time you run using this tag. Alternatively, run `docker pull docker.io/superseriousbusiness/gotosocial:snapshot` manually just before use.
#### Binary release .tar.gz
To run from main using a binary release, download the appropriate .tar.gz file for your architecture from our [self-hosted Minio S3 repository](https://minio.s3.superseriousbusiness.org/browser/gotosocial-snapshots).
Snapshot binary releases in the S3 bucket are keyed by Github commit hash. To get the latest one, sort by Last Modified, or check out the list of commits [here](https://github.com/superseriousbusiness/gotosocial/commits/main), copy the SHA of the latest one, and paste it in the Minio console filter. Snapshot binary releases are expired after 28 days, to keep our hosting costs down.
Snapshot binary releases in the S3 bucket are keyed by commit hash. To get the latest one, sort by Last Modified, or check out the list of commits [here](https://codeberg.org/superseriousbusiness/gotosocial/commits/main), copy the SHA of the latest one, and paste it in the Minio console filter. Snapshot binary releases are expired after 28 days, to keep our hosting costs down.
### From Source
Instructions for building GoToSocial from source are in the [CONTRIBUTING.md](https://github.com/superseriousbusiness/gotosocial/blob/main/CONTRIBUTING.md) file.
Instructions for building GoToSocial from source are in the [CONTRIBUTING.md](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md) file.
### Third-party Packaging
@ -298,11 +392,12 @@ You can also deploy your own instance of GoToSocial with the help of:
- [Ansible Playbook (MASH)](https://github.com/mother-of-all-self-hosting/mash-playbook): The playbook supports a many services, including GoToSocial. [Documentation](https://github.com/mother-of-all-self-hosting/mash-playbook/blob/main/docs/services/gotosocial.md)
- [GoToSocial Helm Chart](https://github.com/fSocietySocial/charts/tree/main/charts/gotosocial) by [0hlov3](https://github.com/0hlov3).
<!--releases-end-->
---
## Contributing
You would like to contribute to GtS? Great! ❤️❤️❤️ Check out the issues page to see if there's anything you intend to jump in on, and read the [CONTRIBUTING.md](https://github.com/superseriousbusiness/gotosocial/blob/main/CONTRIBUTING.md) file for guidelines and setting up your dev environment.
You would like to contribute to GtS? Great! ❤️❤️❤️ Check out the issues page to see if there's anything you intend to jump in on, and read the [CONTRIBUTING.md](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md) file for guidelines and setting up your dev environment.
---
@ -310,7 +405,7 @@ You would like to contribute to GtS? Great! ❤️❤️❤️ Check out the iss
For questions and comments, you can [join our Matrix space](https://matrix.to/#/#gotosocial-space:superseriousbusiness.org) at `#gotosocial-space:superseriousbusiness.org`. This is the quickest way to reach the devs. You can also mail [admin@gotosocial.org](mailto:admin@gotosocial.org).
For bugs and feature requests, please check to see if there's [already an issue](https://github.com/superseriousbusiness/gotosocial/issues), and if not, open one or use one of the above channels to make a request (if you don't have a Github account).
For bugs and feature requests, please check to see if there's [already an issue](https://codeberg.org/superseriousbusiness/gotosocial/issues), and if not, open one or use one of the above channels to make a request (if you don't have a Codeberg account).
---
@ -349,6 +444,7 @@ The following open source libraries, frameworks, and tools are used by GoToSocia
- [superseriousbusiness/oauth2](https://github.com/superseriousbusiness/oauth2) forked from [go-oauth2/oauth2](https://github.com/go-oauth2/oauth2); OAuth server framework and token handling. [MIT License](https://spdx.org/licenses/MIT.html).
- [superseriousbusiness/activity](https://code.superseriousbusiness.org/activity) forked from [go-fed/activity](https://github.com/go-fed/activity); Golang ActivityPub/ActivityStreams library. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [superseriousbusiness/exif-terminator](https://code.superseriousbusiness.org/exif-terminator); EXIF data removal. [GNU AGPL v3 LICENSE](https://spdx.org/licenses/AGPL-3.0-or-later.html).
- [superseriousbusiness/oauth2](https://code.superseriousbusiness.org/oauth2) forked from [go-oauth2/oauth2](https://github.com/go-oauth2/oauth2); OAuth server framework and token handling. [MIT License](https://spdx.org/licenses/MIT.html).
- [tdewolff/minify](https://github.com/tdewolff/minify); HTML minification for Markdown-submitted posts. [MIT License](https://spdx.org/licenses/MIT.html).
@ -390,10 +488,10 @@ Sloth logo by [Anna Abramek](https://abramek.art/).
The Creative Commons Attribution-ShareAlike 4.0 International License license applies specifically to the following files and subdirectories of this repository:
- [sloth logo png](https://github.com/superseriousbusiness/gotosocial/blob/main/web/assets/logo.png)
- [sloth logo webp](https://github.com/superseriousbusiness/gotosocial/blob/main/web/assets/logo.webp)
- [sloth logo svg](https://github.com/superseriousbusiness/gotosocial/blob/main/web/assets/logo.svg)
Combined with the above crowdfunding sources, 2023 Alpha development of GoToSocial was funded by a 50,000 EUR grant from the [NGI0 Entrust Fund](https://nlnet.nl/entrust/), via [NLnet](https://nlnet.nl/). See [here](https://nlnet.nl/project/GoToSocial/#ack) for more details. The successful grant application is archived [here](https://github.com/superseriousbusiness/gotosocial/blob/main/archive/nlnet/2022-next-generation-internet-zero.md).
Combined with the above crowdfunding sources, 2023 Alpha development of GoToSocial was funded by a 50,000 EUR grant from the [NGI0 Entrust Fund](https://nlnet.nl/entrust/), via [NLnet](https://nlnet.nl/). See [here](https://nlnet.nl/project/GoToSocial/#ack) for more details. The successful grant application is archived [here](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/archive/nlnet/2022-next-generation-internet-zero.md).
2024 Beta development of GoToSocial is being funded by an additional 50,000 EUR grant from the [NGI0 Entrust Fund](https://nlnet.nl/entrust/), via [NLnet](https://nlnet.nl/).
@ -461,7 +559,7 @@ Combined with the above crowdfunding sources, 2023 Alpha development of GoToSoci

GoToSocial is free software, licensed under the [GNU AGPL v3 LICENSE](https://github.com/superseriousbusiness/gotosocial/blob/main/LICENSE). We encourage forking and changing the code, hacking around with it, and experimenting.
GoToSocial is free software, licensed under the [GNU AGPL v3 LICENSE](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/LICENSE). We encourage forking and changing the code, hacking around with it, and experimenting.
See [here](https://www.gnu.org/licenses/why-affero-gpl.html) for the differences between AGPL versus GPL licensing, and [here](https://www.gnu.org/licenses/gpl-faq.html) for FAQ's about GPL licenses, including the AGPL.
@ -13,10 +13,10 @@ Big thank you to all of our [Open Collective](https://opencollective.com/gotosoc
- [Beta Aims](#beta-aims)
- [Timeline](#timeline)
- [Mid 2023](#mid-2023)
- [Mid/late 2023](#midlate-2023)
- [Mid/late 2023](#mid-late-2023)
- [Early 2024](#early-2024)
- [BETA milestone](#beta-milestone)
- [Remainder 2024 - early 2025](#remainder-2024---early-2025)
- [Remainder 2024 - early 2025](#remainder-2024-early-2025)
- [On the way out of BETA to STABLE RELEASE](#on-the-way-out-of-beta-to-stable-release)
- [Wishlist](#wishlist)
@ -47,13 +47,13 @@ What follows is a rough timeline of features that will be implemented on the roa
### Mid 2023
- [x] **Hashtags** -- implement federating hashtags and viewing hashtags to allow users to discover posts that they might be interested in. (Done! https://github.com/superseriousbusiness/gotosocial/pull/2032).
- [x] **Hashtags** -- implement federating hashtags and viewing hashtags to allow users to discover posts that they might be interested in. (Done! https://codeberg.org/superseriousbusiness/gotosocial/pulls/2032).
### Mid/late 2023
- [x] **Polls** -- implementing parsing, creating, and voting in polls. (Done! https://github.com/superseriousbusiness/gotosocial/pull/2330)
- [x] **Mute posts/threads** -- opt-out of notifications for replies to a thread; no longer show a given post in your timeline. (Done! https://github.com/superseriousbusiness/gotosocial/pull/2278)
- [x] **Limited peering/allowlists** -- allow instance admins to limit federation with other instances by default. (Done! https://github.com/superseriousbusiness/gotosocial/pull/2200)
- [x] **Polls** -- implementing parsing, creating, and voting in polls. (Done! https://codeberg.org/superseriousbusiness/gotosocial/pulls/2330)
- [x] **Mute posts/threads** -- opt-out of notifications for replies to a thread; no longer show a given post in your timeline. (Done! https://codeberg.org/superseriousbusiness/gotosocial/pulls/2278)
- [x] **Limited peering/allowlists** -- allow instance admins to limit federation with other instances by default. (Done! https://codeberg.org/superseriousbusiness/gotosocial/pulls/2200)
### Early 2024
@ -71,12 +71,12 @@ These are provided in no specific order.
- [x] **Filters v2** -- implement v2 of the filters API.
- [x] **Mute accounts** -- mute accounts to prevent their posts showing up in your home timeline (optional: for limited period of time).
- [x] **Non-replyable posts** -- design a non-replyable post path for GoToSocial based on https://github.com/mastodon/mastodon/issues/14762#issuecomment-1196889788; allow users to create non-replyable posts.
- [] **Block + allow list subscriptions** -- allow instance admins to subscribe their instance to plaintext domain block/allow lists (much of the work for this is already in place).
- [x] **Block + allow list subscriptions** -- allow instance admins to subscribe their instance to domain block/allow lists.
- [x] **Direct conversation view** -- allow users to easily page through all direct-message conversations they're a part of.
- [] **Oauth token management** -- create / view / invalidate OAuth tokens via the settings panel.
- [] **Status EDIT support** -- edit statuses that you've created, without having to delete + redraft. Federate edits out properly.
- [x] **Oauth token management** -- create / view / invalidate OAuth tokens via the settings panel.
- [x] **Status EDIT support** -- edit statuses that you've created, without having to delete + redraft. Federate edits out properly.
- [ ] **Fediverse relay support** -- publish posts to relays, pull posts from relays.
- [] **Two factor authentication (2fa)** -- allow users to enable 2FA for their account via the settings panel, enforce 2FA on login.
- [x] **Two factor authentication (2fa)** -- allow users to enable 2FA for their account via the settings panel, enforce 2FA on login.
- [ ] **Moderation: Append content warning / mark-as-sensitive all content from an instance/account**.
Unsure: Friendica and GoToSocial still don't federate properly with one another (https://github.com/superseriousbusiness/gotosocial/issues/169) so it's hard to test this.
Unsure: Friendica and GoToSocial still don't federate properly with one another (https://codeberg.org/superseriousbusiness/gotosocial/issues/169) so it's hard to test this.
> Abstract: Can you explain the whole project and its expected outcome(s). (you have 1200 characters)
@ -87,8 +87,8 @@ Thirdly, we want to make GtS as customizable as possible by allowing admins to e
The main technical challenges we foresee on the project are:
1. Ensuring compatibility with other AP servers (see here: https://github.com/superseriousbusiness/gotosocial/projects/4).
2. Ensuring compatibility with clients that use the Mastodon API (see here: https://github.com/superseriousbusiness/gotosocial/projects/5).
1. Ensuring compatibility with other AP servers (see federation issues: https://codeberg.org/superseriousbusiness/gotosocial/issues?labels=378188).
2. Ensuring compatibility with clients that use the Mastodon API (see client compatibility issues: https://codeberg.org/superseriousbusiness/gotosocial/issues?labels=378194).
3. Designing nuanced federation safety features that allow instance admins to screen federation without totally breaking it. This will require careful design discussions and lots of testing.
4. Implementing our own open-source http signature library with a reference implementation of the latest draft of the http signature proposal: https://httpwg.org/http-extensions/draft-ietf-httpbis-message-signatures.html.
5. Writing + maintaining our own extensions to the AP protocol (see below).
> Abstract: Can you explain the whole project and its expected outcome(s). (you have 1200 characters)
@ -20,7 +20,7 @@ GtS emphasizes user safety and privacy. Unlike other AP servers, it always requi
GtS values ease of deployment and maintenance; this means low system requirements, simple configuration, minimal external dependencies, and clear documentation. GtS makes it easy + affordable for self-hosting newcomers to set up a Fediverse server on low- (or even solar-) powered equipment they might have lying around at home.
GtS began development in Feb 2021. It is still in Alpha, and we hope to use NLNet funding to bring it up to the Beta phase. The project roadmap (https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md) gives more information on what we have planned.
GtS began development in Feb 2021. It is still in Alpha, and we hope to use NLNet funding to bring it up to the Beta phase. The project roadmap (https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/ROADMAP.md) gives more information on what we have planned.
> Have you been involved with projects or organisations relevant to this project before? And if so, can you tell us a bit about your contributions? (Optional) This can help us determine if you are the right person to undertake this effort.
@ -45,7 +45,7 @@ Aside from GoToSocial, I've also made small PRs upstream to the ActivityPub libr
Currently, GoToSocial receives about €22/week from LiberaPay donations - https://liberapay.com/gotosocial. I have been paying my own costs for working on the project from my savings, which is unfortunately not sustainable for a lot longer.
The requested NLNet budget will be used to fund the remaining Alpha portion of development, and bring GoToSocial into the Beta phase (see the roadmap - https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md). In practical terms, this means paying myself to work full time on the project for one year, and paying for contributions from other developers as well.
The requested NLNet budget will be used to fund the remaining Alpha portion of development, and bring GoToSocial into the Beta phase (see the roadmap - https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/ROADMAP.md). In practical terms, this means paying myself to work full time on the project for one year, and paying for contributions from other developers as well.
To pay my living costs + rent I need to make about €2,000/month after tax, working full time. In Belgium, that equates to about €3,000/month, which is €36,000 for one year of work. Naively calculated at 40 hours / week, that's €18.75 per hour.
@ -83,8 +83,8 @@ Thirdly, we want to make GtS as customizable as possible by allowing admins to e
The main technical challenges we foresee on the project are:
1. Ensuring compatibility with other AP servers (see here: https://github.com/superseriousbusiness/gotosocial/projects/4).
2. Ensuring compatibility with clients that use the Mastodon API (see here: https://github.com/superseriousbusiness/gotosocial/projects/5).
1. Ensuring compatibility with other AP servers (see federation issues: https://codeberg.org/superseriousbusiness/gotosocial/issues?labels=378188).
2. Ensuring compatibility with clients that use the Mastodon API (see client compatibility issues: https://codeberg.org/superseriousbusiness/gotosocial/issues?labels=378194).
3. Designing nuanced federation safety features that allow instance admins to screen federation without totally breaking it. This will require careful design discussions and lots of testing.
4. Implementing our own open-source http signature library with a reference implementation of the latest draft of the http signature proposal: https://httpwg.org/http-extensions/draft-ietf-httpbis-message-signatures.html.
5. Writing + maintaining our own extensions to the AP protocol (see below).
This document is the application on behalf of GoToSocial for funding from the [NLnet](https://nlnet.nl) [NGI Zero Commons fund](https://nlnet.nl/commonsfund/), April 2025. See [here](https://nlnet.nl/propose/).
> Abstract: Can you explain the whole project and its expected outcome(s). (you have 1200 characters)
GoToSocial (GtS) is an ActivityPub social network server, which provides a lightweight, simple entryway into Fediverse hosting. It is comparable to (but distinct from) projects such as Mastodon, Friendica, and PixelFed.
GtS emphasizes user safety and privacy. Unlike other AP servers, it always requires http signatures, and makes a strong differentiation between 'public' and other kinds of posts. It also makes it very easy for admins to block instances they don't want to interact with, by allowing them to subscribe to block lists or allow lists, and to import blocks, ensuring that users stay safe.
GtS values ease of deployment and maintenance; this means low system requirements, simple configuration, minimal external dependencies, and clear documentation. GtS makes it easy + affordable for self-hosting newcomers to set up a Fediverse server on low- (or even solar-) powered equipment they might have lying around at home.
GtS began development in Feb 2021, and entered Beta in 2024. We hope to use NLnet funding to continue tuning performance and adding features as we work towards a 1.0 release.
> Have you been involved with projects or organisations relevant to this project before? And if so, can you tell us a bit about your contributions? (Optional) This can help us determine if you are the right person to undertake this effort. (max 2500 characters)
I have been working on GoToSocial since the beginning of the project, first independently, paying myself from my savings, and then thanks to two previous grants from NLnet. My colleague Kim has a similar trajectory, as they now work full time on the project, again thanks to NLnet.
Over the last years we have put many thousands of hours of work into the project: writing code and documentation, fixing bugs, communicating with contributors and doing code review, deploying infrastructure for project builds and discussion, doing project planning, and answering user questions.
Aside from our work on GoToSocial, we also maintain a fork of the Activity library (https://codeberg.org/superseriousbusiness/activity), a fork of the standalone Mastodon frontend customized for GoToSocial (https://codeberg.org/superseriousbusiness/masto-fe-standalone, deployed at https://masto-fe.superseriousbusiness.org), and Kim in particular maintains a large amount of libraries used by the project (https://codeberg.org/gruf), particularly go-ffmpreg (https://codeberg.org/gruf/go-ffmpreg).
## Requested Support
> Explain what the requested budget will be used for?
> Does the project have other funding sources, both past and present?
> (If you want, you can in addition attach a budget at the bottom of the form)
> Explain costs for hardware, human labor (including rates used), travel cost to technical meetings, etc. (max 2500 characters, be concise)
GoToSocial has received two NLnet grants previously, one in 2022-2023, for 50k euros, and another one in 2024-2025, for 75k euros, which we shared between the two of us. These grants went towards paying living costs for myself and Kim (rent, groceries, utilities, taxes, etc), while we both worked full time on the project.
For our first grant we underbudgeted our own costs and ended up underpaying ourselves. We better estimated the second grant, but still had some issues doing more work than we budgeted for, taking account of bug fixes, extra features, and release coordination.
With the benefit of experience, this time we intend to budget more sensibly so that we don't end up going into our overdrafts before the end of each milestone, hence we are asking for a larger amount of funding: 100k euros in total, or 50k euros each per year. This amount of money is comparable to the rate for a mid/senior-level developer in the countries we live in, and should allow us to pay our costs without panic.
Happily, we receive a decent amount of money per month via OpenCollective (https://opencollective.com/gotosocial), which allows us to pay for costs (Greenhost.net) for our CI/CD + snapshot distribution server. It also allows us to pay our freelance colleague f0x for the contributions they are able to make when school is not too busy. As such, NLnet money does not need to be used for anything besides mine and Kim's living costs.
This year, we would like to use the NGI Zero Commons grant to fund development of the following efforts (more tbd):
- Add functionality to allow users and admins to configure cleanup of old statuses and accounts from the database, to keep database sizes smaller.
- Implement better threading support when statuses are deleted (ie., store + show status tombstones).
- Improve search performance and add full-text-search (SQLite, Postgres).
- Add additional in-memory caches for frontend object types (statuses, notifications, etc) to reduce database calls and improve response times.
- Add support for subscribing to relays, and allowing GoToSocial itself to act as a relay, improving connectivity with other instances.
- Add an opt-in profile directory to make it easier to discover accounts on an instance.
- Implement admin panel section to track unreachable instances, so that admins can tell whether another instance has shut down, and take appropriate action.
> Compare your own project with existing or historical efforts
> E.g. what is new, more thorough or otherwise different. (max 4000 characters, be concise)
ActivityPub is now a popular protocol, with a proliferation of AP implementations like Mastodon, Akkoma, Lemmy, Misskey (and its many forks), Pixelfed, WriteFreely, Wordpress, and more, each with its own focus and purpose. As strong as many of these implementations are, however, they are not without their downsides.
For instance, Mastodon and Pixelfed both lean more towards replicating existing corporate social media efforts (Twitter and Instagram respectively), which is offputting for many users. These two implementations are also complex to install and maintain, which puts many would-be admins off hosting their own servers, and leads to a concentration of users on developer-run servers like mastodon.social and pixelfed.social, which breaks the promise of decentralization.
Other ActivityPub-enabled microblogging softwares like Honk and Snac2 have fewer moving parts and lower system requirements, which has led to a surge of deployments of Snac2 in particular. However, their implementation of the Mastodon client API (the de-facto client API of the fediverse, for better or worse), misses some features, and the barebones admin functionality is not user-friendly for people unaccustomed to using the command line.
In addition, some other fediverse projects have a heavy front-end UI which results in a poor experience on low-bandwidth connections or low-powered devices.
GoToSocial's continued aim is to strike a balance between featureful but fairly resource-intensive AP implementations like Mastodon, and lighter and simpler AP implementations like Snac2 and Honk.
Firstly, GtS is small, easy to run, and very well documented. It uses about 200-300MiB of memory on average, so it can be deployed on tiny VPSs for cheap, and on single-board computers. It has no dependencies on things like ffmpeg or on-system SQLite, as everything is virtualized inside the single binary using WASM/Wazero. This means that people who want to run GoToSocial don't need to install or maintain anything else on the host, and it is very easy for third parties like Yunohost to package and distribute.
Secondly, the admin/settings panel offers admins and users the ability to easily customize their profiles and adjust the way that their instance looks, feels, and federates, and to handle day-to-day admin tasks like reviewing reports, blocking or allowing other instances, etc. The web view of profiles is rendered in simple HTML + CSS; Javascript is not required, but is used for progressive enhancement if available. This makes it relatively easy to view a GoToSocial profile on a mobile device with poor connection, on a lower-end laptop etc.
Thirdly, it provides strong safety features thanks to strict block implementation, always-on HTTP signature authentication, interaction controls, and allowing users to choose what visibility of level of posts can be viewed on their profile. The allowlist subscription functionality we added in 2024 is also critical here, as it allows groups of instances to easily federate only with each other, forming "islands" that can be more easily moderated than fully open federation.
Fourthly, we have been -- and continue to be -- fastidious with our Mastodon client API implementation, which means that GoToSocial can be used with a wide variety of clients that provide different experiences to the user. It even works with apps for Pixelfed, so user's can use a GoToSocial account for 'gram-style media-only posting.
> What are significant technical challenges you expect to solve during the project, if any? (optional but recommended, max 5000 characters)
Many of the technical challenges we expect to overcome during this development period are specific to the development efforts we will undertake as part of this grant:
- Status cleanup: Ensure that cleanup processes are capable of being regularly scheduled asynchronously, while not consuming all available server resources (with what will likely involve scanning the entirety of our largest database table!). This may require some clever indexing and/or marking of statuses as expirable in advance.
- Status tombstones: figure out whether we can write a migration to retroactively rethread old statuses that have become unlinked due to deletes.
- Relay support: figure out whether adding support for relay mode will require a separate relay binary, and if so, refactor sections of the codebase into libraries that can be shared by that binary.
- Relay support: make sure GoToSocial can subscribe to both existing relay services, as well as GoToSocial relays (this will probably involve lots of dipping into the codebases of existing relay services like fedi buzz, to figure out what they're doing). And vice versa: ensure that existing fedi implementations with relay support can subscribe to GoToSocial relays.
- Relay support: make sure that DB sizes and memory usage don't become too burdensome given the amount of statuses that relays are likely to process compared to a vanilla instance.
- Profile directory: ensure "discoverable" flag is respected; optimize required new database queries to ensure they use existing indexes (or figure out which new ones need to be created).
- Search support: ensure that the same functionality and performance is offered by both Postgres and SQLite; possibly refactor our database wrappers and migration code for this.
- Unreachable instances: develop a reasonable heuristic to determine whether an instance is unreachable; work out the best way of storing this information in the database and presenting it to admins via the settings panel.
Other technical challenges we will (continue to) address in the near future are not related to any specific milestone task:
- Ensure continued compatibility of GoToSocial with other fedi software projects.
- Ensure continued compatibility of GoToSocial with Mastodon API client apps.
- Refactor old parts of the codebase to increase readability and remove bugs.
- Make performance tweaks to the codebase wherever necessary (reduce CPU usage, improve memory usage).
- Increase coverage of our test suites.
- Continue to support seamless database migration from old versions of GoToSocial to newer ones.
- Refactor some of the frontend settings panel code to maximize code reuse and minimize compiled javascript size, before adding lots of new functionality.
- Move our CI/CD infrastructure and code repository from Github to Codeberg with minimal disruption to our work.
> Describe the ecosystem of the project, and how you will engage with relevant actors and promote the outcomes. E.g. which actors will you involve? Who should run or deploy your solution to make it a success? (max 2500 characters, be concise)
Much of the work we do involves debugging and solving interoperability issues with other federated softwares, which requires keeping communication channels open with the maintainers of those, and figuring out who needs to change what in order for the issue to be resolved. We've done that a lot over the last year or so:
- Fixed interop with Bandwagon: https://github.com/EmissarySocial/bandwagon/issues/152
- Fixed interop with Iceshrimp: https://codeberg.org/superseriousbusiness/gotosocial/issues/1947
- Coordinated interop with Mastodon: https://codeberg.org/superseriousbusiness/gotosocial/pulls/3703
- Fixed federation with Gancio: https://codeberg.org/superseriousbusiness/gotosocial/issues/3875
- Alerted Pixelfed of AP serialization issues: https://github.com/pixelfed/pixelfed/issues/5642
- Cajoled Bluesky into adding user-agent headers: https://github.com/bluesky-social/atproto/issues/3504
- Help out Writefreely with http signature request issues: https://github.com/writefreely/writefreely/issues/661#issuecomment-1951367449
- Debug federation with Lemmy along with one of the Lemmy devs: https://codeberg.org/superseriousbusiness/gotosocial/issues/2697
For GoToSocial-specific extensions to ActivityPub, we've also diligently documented what we've done so far, and exposed a GoToSocial namespace so that remote softwares can easily incorporate GtS extensions if they want to: https://docs.gotosocial.org/en/latest/federation/interaction_policy/, https://gotosocial.org/ns.
This is all part and parcel of our goal for GoToSocial to be a "good citizen" in terms of how it federates, and how we fit into the larger ActivityPub microblogging ecosystem. We intend to keep doing this!
## Attachments
> Attachments: add any additional information about the project that may help us to gain more insight into the proposed effort, for instance a more detailed task description, a justification of costs or relevant endorsements. Attachments should only contain background information, please make sure that the proposal without attachments is self-contained and concise. Don't waste too much time on this. Really.
// Version is the version of GoToSocial being used.
@ -41,27 +40,22 @@ func main() {
// override version in config store
config.SetSoftwareVersion(version)
// instantiate the root command
rootCmd:=&cobra.Command{
Use:"gotosocial",
Short:"GoToSocial - a fediverse social media server",
Long:"GoToSocial - a fediverse social media server\n\nFor help, see: https://docs.gotosocial.org.\n\nCode: https://github.com/superseriousbusiness/gotosocial",
// before running any other cmd funcs, we must load config-path
returnconfig.LoadEarlyFlags(cmd)
},
SilenceErrors:true,
SilenceUsage:true,
}
rootCmd:=new(cobra.Command)
rootCmd.Use="gotosocial"
rootCmd.Short="GoToSocial - a fediverse social media server"
rootCmd.Long="GoToSocial - a fediverse social media server\n\nFor help, see: https://docs.gotosocial.org.\n\nCode: https://codeberg.org/superseriousbusiness/gotosocial"
rootCmd.Version=version
rootCmd.SilenceErrors=true
rootCmd.SilenceUsage=true
// attach global flags to the root command so that they can be accessed from any subcommand
config.AddGlobalFlags(rootCmd)
// Register global flags with root.
config.RegisterGlobalFlags(rootCmd)
// add subcommands
// Add subcommands with their flags.
rootCmd.AddCommand(serverCommands())
rootCmd.AddCommand(debugCommands())
rootCmd.AddCommand(adminCommands())
rootCmd.AddCommand(migrationCommands())
// Testrigcmd will only be set when debug is enabled.
iftestrigCmd:=testrigCommands();testrigCmd!=nil{
@ -70,7 +64,7 @@ func main() {
log.Fatal("gotosocial must be built and run with the DEBUG enviroment variable set to enable and access testrig")
For PostgreSQL, you'll want to use `postgresql_databases` instead.
The file mentioned in `patterns_from` can be created by transforming the output from the GoToSocial CLI media [`list-attachments`](cli.md#gotosocial-admin-media-list-attachments) and [`list-emojis`](cli.md#gotosocial-admin-media-list-emojis) commands. In order to generate the right patterns you can use the [`media-to-borg-patterns.py`](https://github.com/superseriousbusiness/gotosocial/tree/main/example/borgmatic/media-to-borg-patterns.py) script. How Borg patterns work is explained in [their documentation](https://man.archlinux.org/man/borg-patterns.1).
The file mentioned in `patterns_from` can be created by transforming the output from the GoToSocial CLI media [`list-attachments`](cli.md#gotosocial-admin-media-list-attachments) and [`list-emojis`](cli.md#gotosocial-admin-media-list-emojis) commands. In order to generate the right patterns you can use the [`media-to-borg-patterns.py`](https://codeberg.org/superseriousbusiness/gotosocial/tree/main/example/borgmatic/media-to-borg-patterns.py) script. How Borg patterns work is explained in [their documentation](https://man.archlinux.org/man/borg-patterns.1).
You'll need to put that file on your GoToSocial instance and make sure the file is executable. It requires Python 3 which you will already have if you have Borg and Borgmatic installed. It only depends on the Python standard library.
@ -186,7 +186,7 @@ You'll need to put that file on your GoToSocial instance and make sure the file
For this to work reliably, you should ensure that the [storage-local-base-path](../configuration/storage.md) in your GoToSocial configuration uses an absolute path. Otherwise you'll have to tweak the paths yourself.
```sh
$ gotosocial admin media list-attachments --local-only | \
$ gotosocial --config-path /path/to/config.yaml admin media list-attachments --local-only | \
/path/to/media-to-borg-patterns.py \
<storage-local-base-path>
```
@ -210,7 +210,7 @@ If you're running Borgmatic as a systemd service, you can [create a drop-in](htt
```ini
[Service]
ExecStartPre=/path/to/gotosocial admin media list-attachments --local-only | /path/to/media-to-borg-patterns.py <storage-local-base-path> /etc/borgmatic/gotosocial_patterns
GoToSocial supports 'blocking'/'suspending' domains that you don't want your instance to federate with. In our documentation, the two terms 'block' and 'suspend' are used interchangeably with regard to domains, because they mean the same thing: preventing your instance and the instance running on the target domain from communicating with one another, effectively cutting off federation between the two instances.
You can view, create, and remove domain blocks and domain allows using the [instance admin panel](./settings.md#federation).
You can view, create, and remove domain blocks and domain allows using the [instance admin panel](./settings.md#domain-permissions).
This document focuses on what domain blocks actually *do* and what side effects are processed when you create a new domain block.
@ -41,9 +41,9 @@ With this in mind, you should only ever treat domain blocking as *one layer* of
Unfortunately, the Fediverse has its share of trolls, many of whom see domain blocking as an adversary to be defeated. To achieve this, they often target instances which use domain blocks to protect users.
As such, there are bots on the Fediverse which scrape instance domain blocks and announce any discovered blocks to the followers of the bot, opening the admin of the blocking instance up to harassment. These bots use the `api/v1/instance/peers?filter=suspended` endpoint of GoToSocial instances to gather domain block information.
As such, there are bots on the Fediverse which scrape instance domain blocks and announce any discovered blocks to the followers of the bot, opening the admin of the blocking instance up to harassment. These bots use the `api/v1/instance/peers?filter=suspended`, `api/v1/instance/peers?filter=blocked`, and/or `api/v1/instance/domain_blocks` endpoints of GoToSocial instances to gather domain block information.
By default, GoToSocial does not expose this endpoint publicly, so your instance will be safe from such scraping. However, if you set `instance-expose-suspended` to `true` in your config.yaml file, you may find that this endpoint gets scraped occasionally, and you may see your blocks being announced by troll bots.
By default, GoToSocial does not expose these endpoints publicly, so your instance will be safe from such scraping. However, if you set `instance-expose-blocklist` to `true` in your config.yaml file, you may find that these endpoints gets scraped occasionally, and you may see your blocks being announced by troll bots.
## What are the side effects of creating a domain block
Via the [admin settings panel](./settings.md#subscriptions), you can create and manage domain permission subscriptions.
Domain permission subscriptions allow you to specify a URL at which a permission list is hosted. Every 24hrs at 11pm (by default), your instance will fetch and parse each list you're subscribed to, in order of priority (highest to lowest), and create domain permissions (or domain permission drafts) based on entries discovered in the lists.
Each domain permission subscription can be used to create domain allow or domain block entries.
!!! warning
Currently, via blocklist subscriptions it is only possible to create "suspend" level domain blocks; other severities are not yet supported. Entries of severity "silence" or "limit" etc. on subscribed blocklists will be skipped.
## Priority
When you specify multiple domain permission subscriptions, they will be fetched and parsed in order of priority, from highest priority (255) to lowest priority (0).
Permissions discovered on lists higher up in the priority ranking will override permissions on lists lower down in the priority ranking.
For example, an instance admin subscribes to two allow lists, "Important List" at priority 255, and "Less Important List" at priority 128. Each of these subscribed lists contain an entry for `good-eggs.example.org`.
The subscription with the higher priority is the one that now creates and manages the domain allow entry for `good-eggs.example.org`.
If the subscription with the higher priority is removed, then the next time all the subscriptions are fetched, "Less Important List" will create (or take ownership of) the domain allow instead.
## Retractions
Sometimes, an entry that was present on a subscribed block or allow list will be removed later by the curator(s) of that list. When this happens, the removed domain permission entry can be said to have been "retracted".
For example, say your instance subscribes to one block list, and that block list contains an entry for `baddies.example.org`. A corresponding domain block for `baddies.example.org` has therefore been created in your database, with the subscription ID of your block list. In other words, the domain block is in force, and is managed by your block list subscription.
At some point, your instance fetches the list again, and this time it sees that the entry for `baddies.example.org` is no longer present in the list, because it has been removed by the list curator(s) (perhaps the admins turned their policies around, or the instance was shut down, etc). Thus, according to your instance, the block for `baddies.example.org` is now a "retracted" domain permission entry.
If the domain permission subscription is set to "Remove retracted permissions," then the now-retracted domain block will be removed from the database, and will no longer be enforced. In this example, that means your instance will start federating (again) with `baddies.example.org`.
If the domain permission subscription is *not* set to "Remove retracted permissions," then instead of the retracted block being removed from the database, it will be kept in the database but "orphaned" -- ie., it will still be in force, but it will be marked as no longer being managed by the subscription. In this example, that means your instance will keep blocking `baddies.example.org`.
!!!! Note "Retracted permissions and other subscriptions"
When a permission is retracted and removed from the database, but an entry for it exists on the list of *another* subscription of a lower priority than the one it was retracted from, then the permission will be recreated as an entry managed by the lower priority list.
For example, say you subscribe to List1 at priority 255, and List2 at priority 128, and `baddies.example.org` is present on both lists. That means the domain block entry will be managed by List1. If List1 later *retracts* the entry, it will be removed from your database (assuming you have "Remove retracted permissions" set). However, as soon as List2 is checked (usually seconds after List1), then an entry for `baddies.example.org` will be created again, but managed by List2 this time.
In other words, it is only when an entry is retracted from *every list you subscribe to* that it will truly be removed.
## Orphan Permissions
Domain permissions (blocks or allows) that are not currently managed by a domain permission subscription are considered "orphan" permissions. This includes permissions that an admin created in the settings panel by hand, entries which were imported manually via the import/export page, or entries that belonged to a subscription but have since been retracted but not removed.
If you wish, when creating a domain permission subscription, you can set ["adopt orphans"](./settings.md#adopt-orphan-permissions) to true for that subscription. If a domain permission subscription that is set to adopt orphans encounters an orphan permission which is *also present on the list at the subscription's URI*, then it will "adopt" the orphan by setting the orphan's subscription ID to its own ID.
For example, an instance admin manually creates a domain block for the domain `horrid-trolls.example.org`. Later, they create a domain permission subscription for a block list that contains an entry for `horrid-trolls.example.org`, and they set "adopt orphans" to true. When their instance fetches and parses the list, and creates domain permission entries from it, then the orphan domain block for `horrid-trolls.example.org` gets adopted by the domain permission subscription. Now, if the domain permission subscription is removed, and the option to remove all permissions owned by the subscription is checked, then the domain block for `horrid-trolls.example.org` will also be removed.
## Fun Stuff To Do With Domain Permission Subscriptions
### 1. Create an allowlist-federation cluster.
Domain permission subscriptions make it possible to easily create allowlist-federation clusters, ie., a group of instances can essentially form their own mini-fediverse, wherein each instance runs in [allowlist federation mode](./federation_modes.md#allowlist-federation-mode), and subscribes to a cooperatively-managed allowlist hosted somewhere.
For example, instances `instance-a.example.org`, `instance-b.example.org`, and `instance-c.example.org` decide that they only want to federate with each other.
Using some version management platform like Codeberg, they host a plaintext-formatted allowlist at something like `https://codeberg.org/our-cluster/allowlist/raw/branch/main/allows.txt`.
The contents of the plaintext-formatted allowlist are as follows:
```text
instance-a.example.org
instance-b.example.org
instance-c.example.org
```
Each instance admin sets their federation mode to `allowlist`, and creates a subscription to create allows from `https://codeberg.org/our-cluster/allowlist/raw/branch/main/allows.txt`, which results in domain allow entries being created for their own domain, and for each other domain in the cluster.
At some point, someone from `instance-d.example.org` asks (out of band) whether they can be added to the cluster. The existing admins agree, and update their plaintext-formatted allowlist to read:
```text
instance-a.example.org
instance-b.example.org
instance-c.example.org
instance-d.example.org
```
The next time each instance fetches the list, a new domain allow entry will be created for `instance-d.example.org`, and it will be able to federate with the other domains on the list.
### 2. Cooperatively manage a blocklist.
Domain permission subscriptions make it easy to collaborate on and subscribe to shared blocklists of domains that host illegal / fashy / otherwise undesired accounts and content.
For example, the admins of instances `instance-e.example.org`, `instance-f.example.org`, and `instance-g.example.org` decide that they are tired of duplicating work by playing whack-a-mole with bad actors. To make their lives easier, they decide to collaborate on a shared blocklist.
Using some version management platform like Codeberg, they host a blocklist at something like `https://codeberg.org/our-cluster/allowlist/raw/branch/main/blocks.csv`.
When someone discovers a new domain hosting an instance they don't like, they can open a pull request or similar against the list, to add the questionable instance to the domain.
For example, someone gets an unpleasant reply from a new instance `fashy-arseholes.example.org`. Using their collaboration tools, they propose adding `fashy-arseholes.example.org` to the blocklist. After some deliberation and discussion, the domain is added to the list.
The next time each of `instance-e.example.org`, `instance-f.example.org`, and `instance-g.example.org` fetch the block list, a block entry will be created for ``fashy-arseholes.example.org``.
### 3. Subscribe to a blocklist, but ignore some of it.
Say that `instance-g.example.org` in the previous section decides that they agree with most of the collaboratively-curated blocklist, but they actually would like to keep federating with ``fashy-arseholes.example.org`` for some godforsaken reason.
This can be done in one of three ways:
1. The admin of `instance-g.example.org` subscribes to the shared blocklist, but they do so with the ["create as drafts"](./settings.md#create-permissions-as-drafts) option set to true. When their instance fetches the blocklist, a draft block is created for `fashy-arseholes.example.org`. The admin of `instance-g` just leaves the permission as a draft, or rejects it, so it never comes into force.
2. Before the blocklist is re-fetched, the admin of `instance-g.example.org` creates a [domain permission exclude](./settings.md#excludes) entry for ``instance-g.example.org``. The domain ``instance-g.example.org`` then becomes exempt/excluded from automatic permission creation, and so the block for ``instance-g.example.org`` on the shared blocklist does not get created in the database of ``instance-g.example.org`` the next time the list is fetched.
3. The admin of `instance-g.example.org` creates an explicit domain allow entry for `fashy-arseholes.example.org` on their own instance. Because their instance is running in `blocklist` federation mode, [the explicit allow overrides the domain block entry](./federation_modes.md#in-blocklist-mode), and so the domain remains unblocked.
### 4. Subscribe directly to another instance's blocklist.
Because GoToSocial is able to fetch and parse JSON-formatted lists of domain permissions, it is possible to subscribe directly to another instance's list of blocked domains via their `/api/v1/instance/domain_blocks` (Mastodon) or `/api/v1/instance/peers?filter=suspended` (GoToSocial) endpoint (if exposed).
For example, the Mastodon instance `peepee.poopoo.example.org` exposes their block list publicly, and the owner of the GoToSocial instance `instance-h.example.org` decides they quite like the cut of the Mastodon moderator's jib. They create a domain permission subscription of type JSON, and set the URI to `https://peepee.poopoo.example.org/api/v1/instance/domain_blocks`. Every 24 hours, their instance will go fetch the blocklist JSON from the Mastodon instance, and create permissions based on entries discovered therein.
## Example lists per content type
Shown below are examples of the different permission list formats that GoToSocial is able to understand and parse.
Each list contains three domains, `bumfaces.net`, `peepee.poopoo`, and `nothanks.com`.
### CSV
CSV lists use content type `text/csv`.
Mastodon domain permission exports generally use this format.
As an alternative to `"comment"`, `"public_comment"` will also work:
```json
[
{
"domain": "bumfaces.net",
"suspended_at": "2020-05-13T13:29:12.000Z",
"public_comment": "big jerks"
},
{
"domain": "peepee.poopoo",
"suspended_at": "2020-05-13T13:29:12.000Z",
"public_comment": "harassment"
},
{
"domain": "nothanks.com",
"suspended_at": "2020-05-13T13:29:12.000Z"
}
]
```
### Plaintext (text/plain)
Plaintext lists use content type `text/plain`.
Note that it is not possible to include any fields like "obfuscate" or "public comment" in plaintext lists, as they are simply a newline-separated list of domains.
@ -31,13 +31,18 @@ When your instance encounters a mention or an announce of a status or account it
## Combining blocks and allows
It is possible to both block and allow the same domain, and the effect of combining these two things depends on which federation mode your instance is currently using.
!!! danger
Combining blocks and allows is a tricky business!

When importing lists of allows and blocks, you should always review the list manually to make sure that you do not inadvertently block a domain that you would prefer not to block, since this can have **very annoying side effects** like removing follows/following, statuses, etc.
When in doubt, always add an explicit allow first as an insurance policy!
It is possible to both block and allow the same domain, and the effect of combining these two things depends on which federation mode your instance is currently using, as explained in the following subsections, which are summarised in a flowchart that you can find below.
### In blocklist mode
As the chart shows, in blocklist mode (the left-hand part of the diagram), an explicit domain allow can be used to override a domain block.
As the chart below shows, in blocklist mode (the left-hand part of the diagram), an explicit domain allow can be used to override a domain block.
This is useful in cases where you are importing a blocklist from someone else, but the imported blocklist contains some instances you would actually prefer not to block. To avoid blocking those instances, you can create explicit domain allows for those instances first. Then, when you import the block list, the explicitly allowed domains will not be blocked, and the side effects of creating a block (deleting statuses, media, relationships etc) will not be processed.
@ -47,16 +52,11 @@ Conversely, if you add an explicit allow for a domain that was blocked, the side
### In allowlist mode
As the chart shows, in allowlist mode (the right-hand part of the diagram) an explicit domain block trumps an explicit domain allow. The following two things must be true in order for an instance to be allowed through, when running in allowlist mode:
As the chart below shows, in allowlist mode (the right-hand part of the diagram) an explicit domain block trumps an explicit domain allow. The following two things must be true in order for an instance to be allowed through, when running in allowlist mode:
1. An explicit domain block **does not exist** for the instance.
2. An explicit domain allow **does exist** for the instance.
If either of the above conditions are not met, the request will be denied.
!!! danger
Combining blocks and allows is a tricky business!
When importing lists of allows and blocks, you should always review the list manually to make sure that you do not inadvertently block a domain that you would prefer not to block, since this can have **very annoying side effects** like removing follows/following, statuses, etc.
When in doubt, always add an explicit allow first as an insurance policy!

GoToSocial serves a `robots.txt` file on the host domain. This file contains rules that attempt to block known AI scrapers, as well as some other indexers. It also includes some rules to ensure things like API endpoints aren't indexed by search engines since there really isn't any point to them.
## Allow/disallow stats collection
You can allow or disallow crawlers from collecting stats about your instance from the `/nodeinfo/2.0` and `/nodeinfo/2.1` endpoints by changing the setting `instance-stats-mode`, which modifies the `robots.txt` file. See [instance configuration](../configuration/instance.md) for more details.
## AI scrapers
The AI scrapers come from a [community maintained repository][airobots]. It's manually kept in sync for the time being. If you know of any missing robots, please send them a PR!
A number of AI scrapers are known to ignore entries in `robots.txt` even if it explicitly matches their User-Agent. This means the `robots.txt` file is not a foolproof way of ensuring AI scrapers don't grab your content.
If you want to block these things fully, you'll need to block based on the User-Agent header in a reverse proxy until GoToSocial can filter requests by User-Agent header.
A number of AI scrapers are known to ignore entries in `robots.txt` even if it explicitly matches their User-Agent. This means the `robots.txt` file is not a foolproof way of ensuring AI scrapers don't grab your content. In addition to this you might want to look into blocking User-Agents via [requester header filtering](request_filtering_modes.md).


The reports section shows a list of reports, originating from your local users, or remote instances (shown anonymously as just the name of the instance, without specific username).
Clicking a report shows if it was resolved (with the reasoning if available), more information, and a list of reported toots if selected by the reporting user. You can also use this view to mark a report as resolved, and fill in a comment. Whatever comment you enter here will be visible to the user that created the report, if that user is from your instance.


Clicking on the username of the reported account opens that account in the 'Accounts' view, allowing you to perform moderation actions on it.
@ -34,11 +34,11 @@ Clicking on the username of the reported account opens that account in the 'Acco
You can use this section to search for an account and perform moderation actions on it.
### Federation
### Domain Permissions


In the federation section you can create, delete, and review explicit domain blocks and domain allows.
In the domain permissions section you can create, delete, and review domain blocks, domain allows, drafts, excludes, and subscriptions.
For more detail on federation settings, and specifically how domain allows and domain blocks work in combination, please see [the federation modes section](./federation_modes.md), and [the domain blocks section](./domain_blocks.md).
@ -46,20 +46,105 @@ For more detail on federation settings, and specifically how domain allows and d
You can enter a domain to suspend in the search field, which will filter the list to show you if you already have a block for it.
Clicking 'suspend' gives you a form to add a public and/or private comment, and submit to add the block. Adding a suspension will suspend all the currently known accounts on the instance, and prevent any new interactions with any user on the blocked instance.
Clicking 'suspend' gives you a form to add a public and/or private comment, and submit to add the block.
Adding a domain block will suspend all currently known accounts from that domain, and prevent any new interactions with the blocked domain.
#### Domain Allows
The domain allows section works much like the domain blocks section, described above, only for explicit domain allows rather than domain blocks.
#### Bulk import/export
#### Import/export
Through the link at the bottom of the Federation section (or going to `/settings/admin/federation/import-export`) you can do bulk import/export of blocklists and allowlists.
In this section you can do bulk import/export of domain permissions in JSON, CSV, or plaintext formats.


Upon importing a list, either through the input field or from a file, you can review the entries in the list before importing a subset. You'll also be warned for entries that use subdomains, providing an easy way to change them to the main domain.
#### Drafts
In this section you can create, search through, accept, and reject domain permission drafts.
Domain permission drafts are domain permissions that have been proposed (either via manual creation or as an entry from a subscribed block / allow list), but have not yet come into force.
Until it is accepted, a domain permission draft will not have any effect on federation with the domain it targets. Upon acceptance, it will be converted into either a domain block or a domain allow, and start being enforced.
#### Excludes
In this section, you can create, search through, and remove domain permission excludes.
Domain permission excludes prevent permissions for a domain (and all subdomains) from being automatically managed by domain permission subscriptions.
For example, if you create an exclude entry for the domain `example.org`, then a blocklist or allowlist subscription will exclude entries for `example.org` and any of its subdomains (`sub.example.org`, `another.sub.example.org` etc.) when creating domain permission drafts and domain blocks/allows.
This functionality allows you to manually manage permissions for excluded domains, in cases where you know you definitely do or don't want to federate with a given domain, no matter what entries are contained in a domain permission subscription.
Note that by itself, creation of an exclude entry for a given domain does not affect federation with that domain at all, it is only useful in combination with permission subscriptions.
#### Subscriptions
In this section, you can create, search through, edit, test, and remove domain permission subscriptions.
Domain permission subscriptions allow you to specify a URL at which a permission list is hosted. Every 24hrs at 11pm (by default), your instance will fetch and parse each subscribed list, and create domain permissions (or domain permission drafts) based on entries in the lists.
##### Title
You can optionally use the title field to set a title for the subscription, as a reminder for yourself and other admins.
For example, you might subscribe to a list at `https://lists.example.org/baddies.csv` and set the title of the subscription to something that reflects the contents of that list, such as "Basic block list (worst of the worst)", or similar.
##### Subscription Priority
When you specify multiple domain permission subscriptions, they will be fetched and parsed in order of priority, from highest priority (255) to lowest priority (0).
Permissions discovered on lists higher up in the priority ranking will override permissions on lists lower down in the priority ranking.
For more information on priority, please see the separate [domain permission subscriptions](./domain_permission_subscriptions.md) document.
##### Permission Type
You can use this dropdown to select whether permissions discovered at the list URL should be created as domain blocks, or domain allows.
##### Content Type
You can use this dropdown to select the content type of the list at the subscribed URL.
Use CSV for Mastodon-style permission lists, plain for plaintext lists of domain names, or JSON for json-exported lists.
##### Basic Auth
Check this box to provide a basic auth username and/or password credential for the subscribed list, which will be sent along with each request to fetch the list.
##### Adopt Orphan Permissions
If you check this box, then any existing domain permissions will become managed by this subscription in the following circumstances:
1. They don't already have a subscription ID (ie., they're not managed by any domain permission subscription).
2. They match a domain permission included in the list at the URL of this subscription.
For more information on orphan permissions, please see the separate [domain permission subscriptions](./domain_permission_subscriptions.md#orphan-permissions) document.
##### Remove Retracted Permissions
This setting controls how retractions are handled by this domain permission subscription: if "Remove retracted permissions" is checked, retracted entries will be removed from the database; if "Remove retracted permissions" is not checked, retracted entries will just be orphaned instead.
For more detail on how retractions work, with examples, please see the separate [domain permission subscriptions](./domain_permission_subscriptions.md#retractions) document.
##### Create Permissions as Drafts
With this box checked (default), any permissions created by this subscription will be created as **drafts** which require manual approval to come into force.
It is recommended to leave this box checked unless you absolutely trust the subscribed list, to avoid inadvertent blocking or allowing of domains you'd rather not block or allow.
##### Test a Subscription
To test whether a subscription can be successfully parsed, first create the subscription, then in the detailed view for that subscription, click on the "Test" button.
If your instance is able to fetch and parse permissions at the subscription URI, then you will see a list of these after clicking "Test". Otherwise, you will see an error message.

## Administration
Instance administration settings.
@ -86,7 +171,7 @@ Custom Emoji will be automatically fetched when included in remote toots, but to
#### Local


This section shows an overview of all the custom emoji enabled on your instance, sorted by their category. Clicking an emoji shows it's details, and provides options to change the category or image, or delete it completely. The shortcode cannot be updated here, you would have to upload it with the new shortcode yourself (and optionally delete the old one).
@ -94,7 +179,7 @@ Below the overview you can upload your own custom emoji, after previewing how th
#### Remote


Through the 'remote' section, you can look up a link to any remote toots (provided the instance isn't suspended). If they use any custom emoji they will be listed, providing an easy way to copy them to the local emoji (for use in your own toots), or disable them ( hiding them from toots).
@ -102,7 +187,7 @@ Through the 'remote' section, you can look up a link to any remote toots (provid
### Instance Settings


Here you can set various metadata for your instance, like the displayed name/title, thumbnail image, (short) description, and contact info.
@ -167,3 +252,11 @@ Links to the set contact account and/or email address will appear on the footer
The selected **contact user** must be an active (not suspended) admin and/or moderator on the instance.
If you're on a single-user instance and you give admin privileges to your main account, you can just fill in your own username here; you don't need to make a separate admin account just for this.
### Instance Custom CSS
custom CSS allows you to further customize the way your instance looks when visited through a browser.
This custom CSS will be applied to all pages of your instance. Users themes and CSS still take precedence over this customization.
See the [Custom CSS](../user_guide/custom_css.md) page for some tips on writing custom CSS for your instance.
@ -17,7 +17,7 @@ You can open new account sign-ups for your instance by changing the variable `ac
A sign-up form for your instance will be available at the `/signup` endpoint. For example, `https://your-instance.example.org/signup`.


Also, your instance homepage and "about" pages will be updated to reflect that registrations are open.
@ -29,11 +29,11 @@ In the meantime, admins and moderators on your instance will receive an email an
Instance admins and moderators can handle a new sign-up by either approving or rejecting it via the "accounts" -> "pending" section in the admin panel.


If you have no sign-ups, the list pictured above will be empty. If you have a pending account sign-up, however, you can click on it to open that account in the account details screen:


At the bottom, you will find actions that let you approve or reject the sign-up.
@ -46,12 +46,14 @@ If you **reject** the sign-up, you may wish to inform the applicant that their s
## Sign-Up Limits
To avoid sign-up backlogs overwhelming admins and moderators, GoToSocial limits the sign-up pending backlog to 20 accounts. Once there are 20 accounts pending in the backlog waiting to be handled by an admin or moderator, new sign-ups will not be accepted via the form.
By default, to avoid sign-up backlogs overwhelming admins and moderators, GoToSocial limits the sign-up pending backlog to 20 accounts. Once there are 20 accounts pending in the backlog waiting to be handled by an admin or moderator, new sign-ups will not be accepted via the form.
New sign-ups will also not be accepted via the form if 10 or more new account sign-ups have been approved in the last 24 hours, to avoid instances rapidly expanding beyond the capabilities of moderators.
By default, new sign-ups will also not be accepted via the form if 10 or more new account sign-ups have been approved in the last 24 hours, to avoid instances rapidly expanding beyond the capabilities of moderators.
In both cases, applicants will be shown an error message explaining why they could not submit the form, and inviting them to try again later.
The limit of sign-ups per day, and the backlog size, can be configured or disabled altogether with the variables `accounts-registration-daily-limit` and `accounts-registration-backlog-limit`. See the [accounts config section](../configuration/accounts.md) for more info.
To combat spam accounts, GoToSocial account sign-ups **always** require manual approval by an administrator, and applicants must **always** confirm their email address before they are able to log in and post.
While GoToSocial runs great on lower-end hardware, some operations are not practical on it, especially
instances with the database on slow storage (think anything that is not an SSD). This document
offers some suggestions on how to work around common issues when running GtS on slow hardware.
## Running database migrations on a different machine
Sometimes a database migration will need to do operations that are taxing on the database's storage.
These operations can take days if the database resides on a hard disk or SD card. If your
database is on slow storage, it can save a lot of time to follow the following procedure:
!!! danger
It might seem tempting to keep GtS running while you run the migrations on another machine, but
doing this will lead to all the posts that are received during the migration post disappearing
once the migrated database is re-imported.
1. Shut down GtS
2. Take a [backup](backup_and_restore.md#what-to-backup-database) of the database
3. Import the database on faster hardware
4. Run the GtS migration on the faster hardware
5. Take a backup of the resultant database
6. Import the resultant backup and overwrite the old database
7. Start GtS with the new version
### Running GtS migrations separately
After you import the database on the faster hardware, you can run the migration without starting
GtS by downloading the *target* GtS version from the [releases](https://codeberg.org/superseriousbusiness/gotosocial/releases) page.
For instance, if you are running `v0.19.2` and you want to upgrade to `v0.20.0-rc1`, download the
latter version. Once you have the binary, set it to executable by running `chmod u+x /path/to/gotosocial`. Afterwards, copy the configuration of the original server, and alter
it with the location of the new database. We copy the configuration in case variables like
the hostname is used in the migration, we want to keep that consistent.
Once everything is in place, you can run the migration like this:
```sh
$ /path/to/gotosocial --config-path /path/to/config migrations run
```
This will run all the migrations, just like GtS would if it was started normally. Once this is done
you can copy the result to the original instance and start the new GtS version there as well, which
will see that everything is migrated and that there's nothing to do except run as expected.
We do not offer any kind of support for deployments of GoToSocial built with the `nowasm` tag described in this section. Such builds should be considered strictly experimental, and any issues that come when running them are none of our business! Please don't open issues on the repo looking for help debugging deployments of `nowasm` builds.
On [supported platforms](../../getting_started/releases.md#supported-platforms), GoToSocial uses the WebAssembly runtime [Wazero](https://wazero.io/) to sandbox `ffmpeg`, `ffprobe`, and `sqlite3` WebAssembly binaries, allowing these applications to be packaged and run inside the GoToSocial binary, without requiring admins to install + manage any external dependencies.
This has the advantage of making it easier for admins to maintain their GoToSocial instance, as their GtS binary is completely isolated from any changes to their system-installed `ffmpeg`, `ffprobe`, and `sqlite`. It's also a bit safer to run `ffmpeg` in this way, as GoToSocial wraps the `ffmpeg` binary in a very constrained file system that doesn't permit the `ffmpeg` binary to access any files other than the ones it's decoding + reencoding. In other words, GoToSocial on supported platforms offers most of the functionality of `ffmpeg` and so on, without some of the headaches.
However, not all platforms are capable of running Wazero in the much-faster "compiler" mode, and have to fall back to the very slow (and resource-heavy) "interpreter" mode. See [this table](https://github.com/tetratelabs/wazero?tab=readme-ov-file#conformance) from Wazero for conformance.
"Interpreter" mode runs so poorly for GoToSocial's use case that it's simply not feasible to run a GoToSocial instance in a stable manner on platforms that aren't 64-bit Linux or 64-bit FreeBSD, as all the memory and CPU get gobbled up by media processing.
However! To enable folks to run **experimental, unsupported deployments of GoToSocial**, we expose the `nowasm` build tag, which can be used to compile a build of GoToSocial that does not use Wazero or WASM at all.
A GoToSocial binary built with `nowasm` will use the [modernc version of SQLite](https://pkg.go.dev/modernc.org/sqlite) instead of the WASM one, and will use on-system `ffmpeg` and `ffprobe` binaries for media processing.
!!! tip
To test if your system is compatible with the standard builds, you can use this command:
`if grep -qE '^flags.* (sse4|LSE)' /proc/cpuinfo; then echo "Your system is supporting GTS!"; else echo "Your system is not supporting GTS, you'll have to use the 'nowasm' builds :("; fi`
To build GoToSocial with the `nowasm` tag, you can pass the tag into our convenience `build.sh` script like so:
```bash
GO_BUILDTAGS=nowasm ./scripts/build.sh
```
In order to run a version of GoToSocial built in this way, you must ensure that `ffmpeg` and `ffprobe` are installed on the host. This is usually as simple as running a command like `doas -u root pkg_add ffmpeg` (OpenBSD), or `sudo apt install ffmpeg` (Debian etc.).
!!! Danger "No really though, it's unsupported"
Again, if running builds of GoToSocial with `nowasm` works for your OS/Arch combination, that's great, but we do not support such builds and we won't be able to help debugging why something doesn't work.
In this section we touch on a number of more advanced topics, primarily related around deploying, operating and tuning GoToSocial.
In this section we touch on a number of more advanced topics, primarily related around building, deploying, operating and tuning GoToSocial.
We consider these topics advanced because applying them incorrectly does have the possibility of causing client and federation issues. Applying any of these configuration changes may also make it harder for you to debug an issue with your GoToSocial instance if you don't understand the changes that you're making.
@ -16,3 +16,4 @@ We consider these topics advanced because applying them incorrectly does have th
* [Tracing](tracing.md)
* [Metrics](metrics.md)
* [Replicating SQLite](replicating-sqlite.md)
* [SQLite on networked storage](sqlite-networked-storage.md)
GoToSocial comes with [OpenTelemetry][otel] based metrics. The metrics are exposed using the [Prometheus exposition format][prom] on the `/metrics` path. The configuration settings are documented in the [Observability configuration reference][obs].
GoToSocial uses the [OpenTelemetry][otel] Go SDK to enable instance admins to expose runtime metrics in the Prometheus metrics format.
Currently the following metrics are collected:
Currently, the following metrics are collected:
* Go performance and runtime metrics
* Gin (HTTP) metrics
* Gin (HTTP server) metrics
* Bun (database) metrics
Metrics can be enable with the following configuration:
## Enabling metrics
To enable metrics, first set the `metrics-enabled` configuration value to `true` in your config.yaml file:
```yaml
metrics-enabled: true
```
Though metrics do not contain anything privacy sensitive, you may not want to allow just anyone to view and scrape operational metrics of your instance.
Then, you will need to set some additional environment variables on the GoToSocial process in order to configure OpenTelemetry to expose metrics in the Prometheus format:
```env
OTEL_METRICS_PRODUCERS=prometheus
OTEL_METRICS_EXPORTER=prometheus
```
By default, this configuration will instantiate an additional HTTP server running alongside the standard GoToSocial HTTP server, which exposes a Prometheus metrics endpoint at `localhost:9464/metrics`.
!!! tip
If you are running GoToSocial using the [example systemd service definition](../../example/gotosocial.service), you can easily set these environment variables by uncommenting the relevant two lines in that file, and reloading + restarting the service.
If you wish, you can further customize this metrics HTTP server by using the following environment variables to change the host and port:
```env
OTEL_EXPORTER_PROMETHEUS_HOST=example.org
OTEL_EXPORTER_PROMETHEUS_PORT=9999
```
## Serving metrics to the outside world
If you have deployed GoToSocial in a "bare-metal" fashion without a reverse proxy, you can expose the metrics endpoint to the outside world by setting `OTEL_EXPORTER_PROMETHEUS_HOST` to your host value. For example, if your GtS instance `host` configuration value is set to `example.org`, you should set `OTEL_EXPORTER_PROMETHEUS_HOST=example.org`. You should then be able to access your metrics at `http://example.org:9464/metrics`. GoToSocial running in this fashion will not serve LetsEncrypt certificates at the metrics endpoint, so you will be limited to using HTTP rather than HTTPS.
If you are using a reverse proxy like Nginx, you can expose the metrics endpoint to the outside world with HTTPS certificates, by putting an additional location stanza in your Nginx configuration above the catch-all `location /` stanza:
```nginx
location /metrics {
proxy_pass http://127.0.0.1:9464;
}
```
This will instruct Nginx to forward requests to `example.org/metrics` to the separate Prometheus server running on port 9464.
## Enabling basic authentication
You can enable basic authentication for the metrics endpoint. On the GoToSocial, side you'll need the following configuration:
Although there is no sensitive data contained in the OTEL runtime statistics exported by Prometheus, you may nevertheless wish to gate access to the `/metrics` endpoint behind some kind of authentication, to prevent every Tom, Dick, and Harry from looking at your runtime stats.
```yaml
metrics-auth-enabled: true
metrics-auth-username: some_username
metrics-auth-password: some_password
You can do this by configuring your reverse proxy to require basic authentication for access to `/metrics`.
In Nginx, for example, you could do this by creating an `htpasswd` file alongside your site in the `sites-available` directory of Nginx, and instructing Nginx to use that file to gate access.
Assuming you followed the [guide for setting up Nginx as your reverse proxy](../getting_started/reverse_proxy/nginx.md), you will already have a file for your Nginx service definition at `/etc/nginx/sites-available/example.org`, where `example.org` is the hostname of your instance.
You can create an `htpasswd` file alongside this file using the following command:
You can scrape that endpoint with a Prometheus instance using the following configuration in your `scrape_configs`:
In the command, be sure to replace `example.org` with your hostname, and `username` with whatever username you want to use.
Now, edit `/etc/nginx/sites-available/example.org` and update your `/metrics` stanza to use the `httpasswd` file. After editing it should look something like this:
Again, replace `example.org` in that snippet with your instance hostname.
When you're finished editing, reload + restart Nginx, and you should see a basic authentication prompt when visiting the `/metrics` endpoint of your instance in your browser.
## Prometheus scrape configuration
You can scrape your `/metrics` endpoint with a Prometheus instance using the following configuration in your `scrape_configs`:
```yaml
- job_name: gotosocial
@ -40,18 +97,12 @@ You can scrape that endpoint with a Prometheus instance using the following conf
- example.org
```
## Blocking external scraping
Change `example.org` to your hostname in the above snippet. If you are not using HTTPS, change the `scheme` value to `http`. If you are not using basic authentication, you can remove the `basic_auth` section. If you are not using a reverse proxy, and metrics are exposed on port 9464, add the port to the host (eg., `example.org` -> `example.org:9464`).
When running with a reverse proxy you can use it to block external access to metrics. You can use this approach if your Prometheus scraper runs on the same machine as your GoToSocial instance and can thus access it internally.
## Viewing metrics on Grafana
For example with nginx, block the `/metrics` endpoint by returning a 404:
```nginx
location /metrics {
return 404;
}
```
Instructions on how to set up Grafana are beyond the scope of this document. However, once you have set up a Grafana to pull from your Prometheus instance, you can import the [example Grafana dashboard](https://codeberg.org/superseriousbusiness/gotosocial/raw/branch/main/example/metrics/gotosocial_grafana_dashboard.json) into your Grafana frontend to easily view GoToSocial Go runtime and HTTP metrics.
If you're using SQLite, the AppArmor profile expects the database in `/gotosocial/db/` so you'll need to adjust your configuration paths or the policy accordingly.
The provided AppArmor example is just intended to get you started. It will still need to be edited depending on your exact setup; consult the comments in the example profile file for more information.
With the policy installed, you'll need to configure your system to use it to constrain the permissions GoToSocial has.
SQLite's operating model assumes the database and the processes or applications using it are colocated on the same host. When running the database in WAL-mode, which is GoToSocial's default, it relies on shared memory between processes to ensure the integrity of your database.
!!! quote
All processes using a database must be on the same host computer; WAL does not work over a network filesystem. This is because WAL requires all processes to share a small amount of memory and processes on separate host machines obviously cannot share memory with each other.
This also means that any other processes accessing the database need to run in the same namespace or container context.
It is in theory possible to run SQLite over Samba, NFS, iSCSI or other forms of filesystems accessed over the network. But it is neither recommended nor supported by the SQLite maintainers, irrespective of whether you're running with write-ahead logging or not. Doing so puts you at risk of database corruption. There is a long history of networked storage having synchronisation issues in their locking primitives, or implementing them with weaker guarantees than what a local filesystem can provide.
Your cloud provider's external volumes, like Hetzner Cloud Volumes, AWS EBS, GCP Persistent Disk etc. may also cause problems, and add variable latency. This has a tendency to severely degrade SQLite's performance.
If you're going to access your database over the network, it's better to use a database with a client-server architecture. GoToSocial supports Postgres for such use-cases.
For the purpose of having a copy of the SQLite database on durable long-term storage, refer to [SQLite streaming replication](replicating-sqlite.md) instead. Remember that neither replication nor using a networked filesystem are a substitute [for having backups](../admin/backup_and_restore.md).
## Settings
!!! danger "Corrupted database"
We do not support running GoToSocial with SQLite on a networked filesystem and we will not be able to help you if you damage your database this way.
Should you really want to take this risk, you'll need to adjust the SQLite [synchronous][sqlite-sync] mode and [journal][sqlite-journal] mode to match the limitations of the filesystem.
We don't provide any recommendations as this will vary based on the solution you're using. See [this issue](https://codeberg.org/superseriousbusiness/gotosocial/issues/3360#issuecomment-2380332027) for what you could potentially set those values to.
GoToSocial comes with [OpenTelemetry][otel] based tracing built-in. It's not wired through every function, but our HTTP handlers and database library will create spans. How to configure tracing is explained in the [Observability configuration reference][obs].
GoToSocial comes with [OpenTelemetry][otel] based tracing built-in. It's not wired through every function, but our HTTP handlers and database library will create spans that may help you debug issues.
## Enabling tracing
To enable tracing on your instance, you must set `tracing-enabled` to `true` in your config.yaml file. Then, you must set the environment variable `OTEL_TRACES_EXPORTER` to your desired tracing format. A list of available options is available [here](https://opentelemetry.io/docs/languages/sdk-configuration/general/#otel_traces_exporter). Once you have changed your config and set the environment variable, restart your instance.
If necessary, you can do further configuration of tracing using the other environment variables listed [here](https://opentelemetry.io/docs/languages/sdk-configuration/general/).
## Ingesting traces
In order to receive the traces, you need something to ingest them and then visualise them. There are many options available including self-hosted and commercial options.
We provide an example of how to do this using [Grafana Tempo][tempo] to ingest the spans and [Grafana][grafana] to explore them. Please beware that the configuration we provide is not suitable for a production setup. It can be used safely for local development and can provide a good starting point for setting up your own tracing infrastructure.
In [`example/tracing`][ext] we provide an example of how to do this using [Grafana Tempo][tempo] to ingest the spans and [Grafana][grafana] to explore them. You can use the files with `docker-compose up -d` to get Tempo and Grafana running.
You'll need the files in [`example/tracing`][ext]. Once you have those you can run `docker-compose up -d` to get Tempo and Grafana running. With both services running, you can add the following to your GoToSocial configuration and restart your instance:
Please be aware that while the example configuration we provide can be used safely for local development and can provide a good starting point for setting up your own tracing infrastructure, it is not suitable for a so-called "production" setup.
## Querying and visualising traces
@ -27,18 +22,23 @@ Once you execute a few queries against your instance, you'll be able to find the
Using TraceQL, a simple query to find all traces related to requests to `/api/v1/instance` would look like this:
```
```traceql
{.http.route = "/api/v1/instance"}
```
If you wanted to see all GoToSocial traces, you could instead run:
```
```traceql
{.service.name = "GoToSocial"}
```
Once you select a trace, a second panel will open up visualising the span. You can drill down from there, by clicking into every sub-span to see what it was doing.


Using the client API requires authentication. This page documents the general flow for retrieving an authentication token with examples for doing this on the CLI using `curl`.
!!! tip
If you want to get an API access token via the settings panel instead, without having to use the command line, see the [Application documentation](https://docs.gotosocial.org/en/latest/user_guide/settings/#applications).
## Create a new application
We need to register a new application, which we can then use to request an OAuth token. This is done by making a `POST` request to the `/api/v1/apps` endpoint. Replace `your_app_name` in the command below with the name you want to use for your application:
```bash
curl \
-X POST \
-H 'Content-Type:application/json' \
-d '{
"client_name": "your_app_name",
@ -20,18 +22,15 @@ curl \
The string `urn:ietf:wg:oauth:2.0:oob` is an indication of what is known as out-of-band authentication - a technique used in multi-factor authentication to reduce the number of ways that a bad actor can intrude on the authentication process. In this instance, it allows us to view and manually copy the tokens created to use further in this process.
Note that `scopes` can be any space-separated combination of:
!!! tip "Scopes"
It is always good practice to grant your application the lowest tier permissions it needs to do its job. e.g. If your application won't be making posts, use `scope=read` or even a subscope of that.
- `read`
- `write`
- `admin`
In this spirit, "read" is used in the example above, which means that the application will be restricted to only being able to do "read" actions.
For a list of available scopes, see [the swagger docs](https://docs.gotosocial.org/en/latest/api/swagger/).
!!! warning
GoToSocial does not currently support scoped authorization tokens, so any token you obtain in this process will be able to perform all actions on your behalf, including admin actions if your account has admin permissions. Nevertheless, it is always good practice to grant your application the lowest tier permissions it needs to do its job. e.g. If your application won't be making posts, use scope=read.
In this spirit, "read" is used in the example above, which means that in the future when scoped tokens are supported, the application will be restricted to only being able to do "read" actions.
You can read more about additional planned OAuth security features [right here](https://github.com/superseriousbusiness/gotosocial/issues/2232).
GoToSocial did not support scoped authorization tokens before version 0.19.0, so if you are using a version of GoToSocial below that, then any token you obtain in this process will be able to perform all actions on your behalf, including admin actions if your account has admin permissions.
A successful call returns a response with a `client_id` and `client_secret`, which we are going need to use in the rest of the process. It looks something like this:
@ -89,7 +88,6 @@ You can do this with another `POST` request that looks like the following:
@ -24,11 +24,11 @@ In case the rate limit is exceeded, an [HTTP 429 Too Many Requests](https://deve
### My rate limit keeps being exceeded! Why?
If you find that your rate limit is regularly being exceeded (both for yourself and other callers) during normal use of your instance, it may be that GoToSocial can't tell the clients apart by IP address. You can investigate this by viewing the logs of your instance. If (almost) all logged IP addresses appear to be the same IP address (something like `172.x.x.x`), then the rate limiting will cause problems.
If you find that your rate limit is regularly being exceeded (both for yourself and other callers) during normal use of your instance, it may be that GoToSocial can't tell the clients apart by IP address. You can investigate this by viewing the logs of your instance. If (almost) all logged client IP addresses appear to be the same IP address (something like `172.x.x.x`), then the rate limiting will cause problems.
This happens when your server is running inside NAT (port forwarding), or behind an HTTP proxy without the correct configuration, causing your instance to see all incoming IP addresses as the same address: namely, the IP address of your reverse proxy or gateway. This means that all incoming requests are *sharing the same rate limit*, rather than being split correctly per IP.
If you are using an HTTP proxy then it's likely that your `trusted-proxies` is not correctly configured. If this is the case, try adding the IP address of your reverse proxy to the list of `trusted-proxies`, and restarting your instance.
If you are using an HTTP proxy then it's likely that your `trusted-proxies` is not correctly configured. See the [trusted-proxies](../configuration/trusted_proxies.md) documentation for more info on how to resolve this.
If you don't have an HTTP proxy, then it's likely caused by NAT. In this case you should disable rate limiting altogether.
GoToSocial stores statuses, accounts, etc, in a database. This can be either [SQLite](https://sqlite.org/index.html) or [Postgres](https://www.postgresql.org/).
By default, GoToSocial will use Postgres, but this is easy to change.
GoToSocial has no default configured database type or address. In most situations, we recommend the use of SQLite.
## SQLite
SQLite, as the name implies, is the lightest database type that GoToSocial can use. It stores entries in a simple file format, usually in the same directory as the GoToSocial binary itself. SQLite is great for small instances and single-board computers, where a dedicated database would be overkill.
To configure GoToSocial to use SQLite, change `db-type` to `sqlite`. The `address` setting will then be a filename instead of an address, so you will want to change it to `sqlite.db` or something similar.
To use SQLite, keep the default `db-type` as `sqlite`. By default the database will be kept in the same directory as the GoToSocial binary, ie., `./sqlite.db`, but you can change this using `db-address` if you want to keep it somewhere else. In the same directory as the `sqlite.db` file, the SQLite driver will also create files `sqlite.db-wal` and `sqlite.db-shm` for temporary storage.
Note that the `:memory:` setting will use an *in-memory database* which will be wiped when your GoToSocial instance stops running. This is for testing only and is absolutely not suitable for running a proper instance, so *don't do this*.
## Postgres
Postgres is a heavier database format, which is useful for larger instances where you need to scale performance, or where you need to run your database on a dedicated machine separate from your GoToSocial instance (or do funky stuff like run a database cluster).
Postgres (aka PostgreSQL) is a heavier database which is useful for larger instances where you need to run your database on a dedicated machine separate from your GoToSocial instance (or do funky stuff like run a database cluster).
You can connect to Postgres using either a Unix socket connection, or via TCP, depending on what you've set as your `db-address` value.
To configure GoToSocial to use Postgres, change `db-type` to `postgres`. The `db-address` setting will then be either a Unix socket connection or a hostname.
GoToSocial also supports connecting to Postgres using SSL/TLS over TCP. If you're running Postgres on a different machine from GoToSocial, and connecting to it via an IP address or hostname (as opposed to just running on localhost), then SSL/TLS is **CRUCIAL** to avoid leaking data all over the place!
@ -42,6 +42,13 @@ create user gotosocial with password 'some_really_good_password';
grant all privileges on database gotosocial to gotosocial;
```
If you start using Postgres after 14, or you encounter `error executing command: error creating dbservice: db migration error: ERROR: permission denied for schema public`, you should grant `CREATE` permission to your db user *(This **must** be run in a postgres shell that's connected to the gotosocial database)*:
```psql
GRANT CREATE ON SCHEMA public TO gotosocial;
SELECT has_schema_privilege('gotosocial', 'public', 'CREATE'); -- should return t
```
GoToSocial makes use of ULIDs (Universally Unique Lexicographically Sortable Identifiers) which will not work in non-English collate environments. For this reason it is important to create the database with `C.UTF-8` locale. To do that on systems which were already initialized with non-C locale, `template0` pristine database template must be used.
If you want to use specific options when connecting to Postgres, you can use `db-postgres-connection-string` to define the connection string. If `db-postgres-connection-string` is defined, all other database related configuration fields will be ignored. For example, we can use `db-postgres-connection-string` to connect to `mySchema`, where the user name is `myUser` and password is `myPass` at `localhost` with the database name of `db`:
@ -18,7 +18,7 @@ gotosocial --config-path ./config.yaml server start
The command expects a file in [YAML](https://en.wikipedia.org/wiki/YAML) or [JSON](https://en.wikipedia.org/wiki/JSON) format.
An example configuration file, with an explanation of each of the config fields, with default and example values, can be found [here](https://github.com/superseriousbusiness/gotosocial/blob/main/example/config.yaml). This example file is also included in release downloads.
An example configuration file, with an explanation of each of the config fields, with default and example values, can be found [here](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/example/config.yaml). This example file is also included in release downloads.
It's recommended to create your own configuration file with only the settings you need to change for your installation. This ensures you don't have to reconcile changes to defaults or adding/updating/removing settings from your configuration file that you haven't changed away from the defaults on every release.
@ -125,4 +125,20 @@ This means in cases where you want to just try changing one thing, but don't wan
Reasonable default values are provided for *most* of the configuration parameters, except in cases where a custom value is absolutely required.
See the [example config file](https://github.com/superseriousbusiness/gotosocial/blob/main/example/config.yaml) for the default values, or run `gotosocial --help`.
See the [example config file](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/example/config.yaml) for the default values, or run `gotosocial --help`.
## `GTS_WAZERO_COMPILATION_CACHE`
On startup, GoToSocial compiles embedded WebAssembly `ffmpeg` and `ffprobe` binaries into [Wazero](https://wazero.io/)-compatible modules, which are used for media processing without requiring any external dependencies.
To speed up startup time of GoToSocial, you can cache the compiled modules between restarts so that GoToSocial doesn't have to compile them on every startup from scratch.
You can instruct GoToSocial on where to store the Wazero artifacts by setting the environment variable `GTS_WAZERO_COMPILATION_CACHE` to a directory, which will be used by GtS to store two smallish artifacts of ~50MiB or so each (~100MiB total).
For an example of this in action, see the [docker-compose.yaml](https://codeberg.org/superseriousbusiness/gotosocial/raw/branch/main/example/docker-compose/docker-compose.yaml), and the [gotosocial.service](https://codeberg.org/superseriousbusiness/gotosocial/raw/branch/main/example/gotosocial.service) example files.
If you want to provide this value to GtS outside of systemd or Docker, you can do so in the following manner when starting up your GtS server:
```bash
GTS_WAZERO_COMPILATION_CACHE=~/gotosocial/.cache ./gotosocial --config-path ./config.yaml server start
These settings let you tune and configure certain observability related behaviours.
GoToSocial uses OpenTelemetry. The metrics and trace exporters can be configured using the standard OpenTelemetry SDK environment variables. For a full reference, see [the OpenTelemetry docs](https://opentelemetry.io/docs/languages/sdk-configuration/).
## Metrics
Before enabling metrics, [read the guide](../advanced/metrics.md) and ensure you've taken the appropriate security measures for your setup.
If you want to expose metrics with (basic) authentication, you'll need to do this with a reverse proxy.
For more information and examples, see the [GtS metrics documentation](https://docs.gotosocial.org/en/latest/advanced/metrics/).
## Settings
```yaml
##############################################
##### OBSERVABILITY AND METRICS SETTINGS #####
##############################################
# String. Header name to use to extract a request or
# trace ID from. Typically set by a loadbalancer or proxy.
#
# Default: "X-Request-Id"
request-id-header: "X-Request-Id"
# Bool. Enable OpenTelemetry based tracing support.
#
# When enabling tracing, you must also configure a traces
# exporter using the OTEL environment variable documented here:
@ -8,6 +8,21 @@ In order to make GoToSocial email sending work, you need an smtp-compatible mail
To validate your configuration, you can use the "Administration -> Actions -> Email" section of the settings panel to send a test email.
!!! warning
Pending an smtp library update, currently only email providers that work with STARTTLS will work with GoToSocial. STARTTLS is generally available over **port 587**.
For more info, see:
- [STARTTLS vs SSL vs TLS](https://mailtrap.io/blog/starttls-ssl-tls/)
For safety reasons, the smtp library used by GoToSocial will refuse to send authentication credentials over an unencrypted connection, unless the mail provider is running on localhost.
!!! info
If your SMTP server offers `STARTTLS` in its EHLO response GoToSocial will try to use it. The SMTP server must hence also have valid SSL certificates. If you're sending mail via localhost and don't want to set up certificates make sure that your SMTP server doesn't announce STARTTLS support. In postfix this can be done via `-o smtpd_tls_security_level=none`.
## Settings
The configuration options for smtp are as follows:
@ -26,6 +41,7 @@ The configuration options for smtp are as follows:
smtp-host: ""
# Int. Port to use to connect to the smtp server.
# In the majority of cases, you should use port 587.
Note that if you don't set `Host`, then email sending via smtp will be disabled, and the other settings will be ignored. GoToSocial will still log (at trace level) emails that *would* have been sent if smtp was enabled.
## Behavior
### SSL
GoToSocial requires your smtp server to present valid SSL certificates. Most of the big services like Mailgun do this anyway, but if you're running your own mail server without SSL for some reason, and you're trying to connect GoToSocial to it, it will not work.
The exception to this requirement is if you're running your mail server (or bridge to a mail server) on `localhost`, in which case SSL certs are not required.
### When are emails sent?
## When are emails sent?
Currently, emails are sent:
- To the provided email address of a new user to request email confirmation when a new account is created via the API.
- To the provided email address of a new user to request email confirmation when a new account is created via the sign up page or API.
- To instance admins when a new account is created in this way.
- To all active instance moderators + admins when a new moderation report is received. By default, recipients are Bcc'd, but you can change this behavior with the setting `smtp-disclose-recipients`.
- To the creator of a report (on this instance) when the report is closed by a moderator.
### Can I test if my SMTP configuration is correct?
Yes, you can use the API to send a test email to yourself. Check the API documentation for the `/api/v1/admin/email/test` endpoint.
### HTML versus Plaintext
## HTML versus Plaintext
Emails are sent in plaintext by default. At this point, there is no option to send emails in html, but this is something that might be added later if there's enough demand for it.
When configuring an object storage backend, the `storage-s3-endpoint`**must not** include the bucket name. That's what `s3-bucket-name` is for. Using subfolders in a bucket isn't currently supported.
## Settings
```yaml
@ -98,6 +100,33 @@ storage-s3-secret-key: ""
# Examples: ["gts","cool-instance"]
# Default: ""
storage-s3-bucket: ""
# String. Key prefix to use for the S3 storage.
# This is optional.
#
# Prefix must end with a trailing slash.
#
# This is useful if you want to store multiple instances in the same bucket,
# or if you want to store your data in a subdirectory of the bucket.
# This has no effect if the storage backend isn't "s3".
#
# Examples: ["gts-instance1/", "gts-instance2/"]
# Default: ""
storage-s3-key-prefix: ""
# String. Bucket lookup type.
#
# If you know what kind of bucket lookup type you need you can specify it here.
#
# Many providers are no longer offering path-style bucket access and only subdomain-style. Then,
# you will need to specify "dns" here instead of the default "auto".
#
# If your provider only supports path-style bucket access, specify "path".
To correctly enforce [rate limiting](../api/ratelimiting.md), GoToSocial relies on the concept of "trusted proxies" in order to accurately determine the IP address of clients accessing your server.
A "trusted proxy" is an intermediate network hop that GoToSocial can be instructed to trust to provide a correct client IP address via an `X-Forwarded-For` or `X-Real-IP` header.
For example, if you are running in a reverse proxy configuration with Docker + Nginx, then the Docker network address of Nginx should be configured as a trusted proxy, since all traffic from the wider internet will come into GoToSocial via Nginx.
If `trusted-proxies` is not set correctly, GoToSocial will see all incoming client IP addresses as the same address. This will lead to rate limiting issues, since GoToSocial uses client IP addresses to bucket rate limits.
!!! tip
If you reached this page via the trusted proxies warning on a GoToSocial page, and the suggested address to add is `127.0.0.1`, then before you try any of the other troubleshooting steps, ensure that your reverse proxy is configured to correctly pass either `X-Forwarded-For` or `X-Real-IP`.
## tl;dr: How to set `trusted-proxies` correctly
If your `trusted-proxies` setting is not correctly configured, you may see the following warning on the web view of your instance (v0.18.0 and above):
> Warning! It looks like trusted-proxies is not set correctly in this instance's configuration. This may cause rate-limiting issues and, by extension, federation issues.
>
> If you are the instance admin, you should fix this by adding `SUGGESTED_IP_RANGE` to your trusted-proxies.
To resolve this, copy the IP range in the message, and edit your `config.yaml` file to add the IP range to your `trusted-proxies`.
!!! tip "You may be getting rate limited even if you don't see the above warning!"
If you're on a version of GoToSocial below v0.18.0, or you're running behind a CDN such as Cloudflare (not recommended), you won't see a warning message. Instead, you'll see in your GoToSocial logs that all client IPs are the same address. In this case, take the recurring client IP value as `SUGGESTED_IP_RANGE`.
In this example, we assume `SUGGESTED_IP_RANGE` to be `172.17.0.1/16` (the default Docker bridge network subnet).
Before (default config):
```yaml
trusted-proxies:
- "127.0.0.1/32"
- "::1"
```
After (new config):
```yaml
trusted-proxies:
- "172.17.0.1/16"
- "127.0.0.1/32"
- "::1"
```
If you are using [environment variables](../configuration/index.md#environment-variables) to configure your instance, you can configure `trusted-proxies` by setting the environment variable `GTS_TRUSTED_PROXIES` to a comma-separated list of IP ranges, like so:
If you are using docker compose, your docker-compose.yaml file should look something like this after the change (note that yaml uses `: ` and not `=`):
Once you have made the necessary configuration changes, **restart your instance** and refresh the home page.
If the message is gone, then the problem is resolved!
If you still see the warning message but with a different suggested IP range to add to `trusted-proxies`, then follow the same steps as above again, including the new suggested IP range in your config in addition to the one you just added.
!!! tip "Cloudflare IP Addresses"
If you are running with a CDN/proxy such as Cloudflare in front of your GoToSocial instance (not recommended), then you may need to add one or more of the Cloudflare IP addresses to your `trusted-proxies` in order to have rate limiting work properly. You can find a list of Cloudflare IP addresses here: https://www.cloudflare.com/ips/
## I can't seem to get `trusted-proxies` configured properly, can I just disable the warning?
There are some situations where it's not practically possible to get `trusted-proxies` configured correctly to detect the real client IP of incoming requests, or where the real client IP is accurate but still shows as being within a private network.
For example, if you're running GoToSocial on your home network, behind a home internet router that cannot inject an `X-Forwarded-For` header, then your suggested entry to add to `trusted-proxies` will look something like `192.168.x.x`, but adding this to `trusted-proxies` won't resolve the issue.
Another example: you're running GoToSocial on your home network, behind a home internet router, and you are accessing the web frontend from a device that's *also* on your home network, like your laptop or phone. In this case, your router may send you directly to your GoToSocial instance without your request ever leaving the network, and so GtS will correctly see *your* client IP address as a private network address, but *other* requests coming in from the wider internet will show their real remote client IP addresses. In this scenario, the `trusted-proxies` warning does not really apply.
If you've tried editing your `trusted-proxies` setting, but you still see the warning, then it's likely that one of the above examples applies to you. You can proceed in one of two ways:
### Add specific exception for your home network (preferred)
If the suggested IP range in the `trusted-proxies` warning looks something like `192.168.x.x`, but you still see other client IPs in your GoToSocial logs that don't start with `192.168`, then try adding a rate limiting exception only for devices on your home network, while leaving rate limiting in place for outside IP addresses.
For example, if your suggestion is something like `192.168.1.128/32`, then swap the `/32` for `/24` so that the range covers `192.168.1.0` -> `192.168.1.255`, and add this to the `advanced-rate-limit-exceptions` setting in your `config.yaml` file.
Before (default config):
```yaml
advanced-rate-limit-exceptions: []
```
After (new config):
```yaml
advanced-rate-limit-exceptions:
- "192.168.1.128/24"
```
If you are using [environment variables](../configuration/index.md#environment-variables) to configure your instance, you can configure `advanced-rate-limit-exceptions` by setting the environment variable `GTS_ADVANCED_RATE_LIMIT_EXCEPTIONS` to a comma-separated list of IP ranges, like so:
If you are using docker compose, your docker-compose.yaml file should look something like this after the change (note that yaml uses `: ` and not `=`):
Once you have made the necessary configuration changes, **restart your instance** and refresh the home page.
### Turn off rate limiting entirely (last resort)
If nothing else works, you can disable rate limiting entirely, which will also disable the `trusted-proxies` check and warning.
!!! warning
Turning off rate limiting entirely should be considered a last resort, as rate limiting helps protect your instance from spam and scrapers.
To turn off rate limiting, set `advanced-rate-limit-requests` to 0 in your `config.yaml`.
Before (default config):
```yaml
advanced-rate-limit-requests: 300
```
After (new config):
```yaml
advanced-rate-limit-requests: 0
```
If you are using [environment variables](../configuration/index.md#environment-variables) to configure your instance, you can configure `advanced-rate-limit-requests` by setting the environment variable `GTS_ADVANCED_RATE_LIMIT_REQUESTS` to 0, like so:
```env
GTS_ADVANCED_RATE_LIMIT_REQUESTS="0"
```
If you are using docker compose, your docker-compose.yaml file should look something like this after the change (note that yaml uses `: ` and not `=`):
```yaml
################################
# BLAH BLAH OTHER CONFIG STUFF #
################################
environment:
############################
# BLAH BLAH OTHER ENV VARS #
############################
GTS_ADVANCED_RATE_LIMIT_REQUESTS: "0"
################################
# BLAH BLAH OTHER CONFIG STUFF #
################################
```
Once you have made the necessary configuration changes, **restart your instance** and refresh the home page.
GoToSocial is just a bare server for the most part and is designed to be used thru external applications. [Semaphore](https://semaphore.social/) in the browser, [Tusky](https://tusky.app/) for Android and [Feditext](https://github.com/feditext/feditext) for iOS, iPadOS and macOS are the best-supported. Anything that supports the Mastodon API should work, other than the features GoToSocial doesn't yet have. Permalinks and profile pages are served directly through GoToSocial as well as the settings panel, but most interaction goes through the apps.
GoToSocial is just a bare server for the most part and is designed to be used thru external applications. [Pinafore](https://pinafore.social/) in the browser, [Tusky](https://tusky.app/) for Android and [Feditext](https://github.com/feditext/feditext) for iOS, iPadOS and macOS are the best-supported. Anything that supports the Mastodon API should work, other than the features GoToSocial doesn't yet have. Permalinks and profile pages are served directly through GoToSocial as well as the settings panel, but most interaction goes through the apps.
## Why aren't my posts showing up on my profile page?
@ -38,4 +38,4 @@ We introduced a sign-up flow in v0.16.0. The server you want to sign up to must
## Why's it still in Beta?
Take a look at the [list of open bugs](https://github.com/superseriousbusiness/gotosocial/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and the [roadmap](https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md) for a more detailed rundown.
Take a look at the [list of open bugs](https://codeberg.org/superseriousbusiness/gotosocial/issues?labels=378161) and the [roadmap](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/ROADMAP.md) for a more detailed rundown.
GoToSocial serves most accounts as the ActivityStreams `Person` type described [here](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-person).
Accounts that users have selected to mark as bot accounts, however, will use the `Service` type described [here](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-service).
This type distinction can be used by remote servers to distinguish between bot accounts and "regular" user accounts.
## Inbox
GoToSocial implements Inboxes for Actors following the ActivityPub specification [here](https://www.w3.org/TR/activitypub/#inbox).
@ -240,6 +248,90 @@ Another difference between GoToSocial and other server implementations is that G
Instead, to build a view of a GoToSocial user's pinned posts, it is recommended that remote instances simply poll a GoToSocial Actor's `featured` collection every so often, and add/remove posts in their cached representation as appropriate.
## `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb`
GoToSocial uses the properties `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb` to indicate whether an actor prefers to hide posts addressed `to` or `cc` public from unauthenticated (ie., logged-out) visitors to web pages, web apps, and web APIs.
Some background for this: many ActivityPub server softwares allow unauthenticated visitors to the profile web page of an actor to see a list of posts that an actor has created that are addressed either `to` or `cc` public. These are often called "public" posts, and "unlisted", "unlocked", or "quiet public" posts, respectively. GoToSocial provides [a settings flag](../user_guide/settings.md#visibility-level-of-posts-to-show-on-your-profile) that allows GtS accounts to hide posts from the web view of their profile, as one layer of protection to make it more of a nuisance to scrape/stalk someone with a GtS account.
While this setting works for hiding posts of an actor *on their own instance*, prior to GoToSocial v0.20.0, this preference was not federated out to other instances, nor was it federated in from other instances. This leads to two problems:
1. Many other fedi server softwares permit logged-out visitors, via a web app, to look up profiles of *remote* accounts, and to see public and unlisted posts created by those accounts. This means that it is trivial to work around the ability of GtS users to hide their posts from the web. For example, say a GtS user at `@someone@gts.example.org` locks down their profile by setting the visibility of posts on their profile to "none"; this prevents visitors to `gts.example.org` from seeing posts, but one could visit eg. `mastodon.example.org` and, while logged out, look up `@someone@gts.example.org`, and see all the posts there that have been sent to, or dereferenced by, actors on `mastodon.example.org`. This makes the GtS user's choice to hide their posts significantly less meaningful.
2. In an effort to support this extra layer of privacy, by default GoToSocial instances do not show posts from remote instances unless they are addressed `to` public. For example, if someone from `mastodon.example.org` were to reply to a post by `@someone@gts.example.org`, and the reply was only addressed `cc` public instead of `to` public, the GtS instance `gts.example.org` would *not* show that reply in the web view, as it could not determine the preferences of the user from `mastodon.example.org` with regard to showing the "quiet public" post to logged-out visitors to the web page. This could be frustrating for the GtS user, as they might want to show a more complete picture of the thread that they started, right there on their instance; this could also frustrate the Mastodon user, as are used to their "quiet public" posts being visible on the web even when logged out.
The actor properties `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb` are a move towards solving these issues, by allowing actors to signal their preferences for hiding or showing `to`- and/or `cc`-public posts to unauthenticated visitors via the web.
For example, the following actor representation indicates that the actor is happy to show both "unlisted" and "public" posts via unauthed web view (this represents the de-facto default for actors on Mastodon and most other server softwares):
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams"
],
"type": "Person",
[... other properties here ...]
"hidesToPublicFromUnauthedWeb": false,
"hidesCcPublicFromUnauthedWeb": false,
[... other properties here ...]
}
```
By contrast, the following indicates that the actor hides "unlisted" posts but is happy to show "public" posts unauthed (this is the default for actors on GtS instances):
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams"
],
"type": "Person",
[... other properties here ...]
"hidesToPublicFromUnauthedWeb": false,
"hidesCcPublicFromUnauthedWeb": true,
[... other properties here ...]
}
```
And the following shows that the actor wants to show no posts unauthed at all:
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams"
],
"type": "Person",
[... other properties here ...]
"hidesToPublicFromUnauthedWeb": true,
"hidesCcPublicFromUnauthedWeb": true,
[... other properties here ...]
}
```
Both `hidesToPublicFromUnauthedWeb` and `hidesCcPublicFromUnauthedWeb` are defined in [the GoToSocial json-ld `@context` document](https://gotosocial.org/ns).
In line with its emphasis on having people opt-in to greater visibility rather than opt-out, when receiving a post from a remote actor that does not set these flags, GoToSocial assumes `hidesToPublicFromUnauthedWeb` = `false`, and `hidesCcPublicFromUnauthedWeb` = `true`. That is, the pre-v0.20.x behavior of GoToSocial is still the default for remote servers that don't (yet) use these flags.
!!! note
While unusual, it's possible for an actor to also specify that they want to show "unlisted" posts but hide "public" ones:
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams"
],
"type": "Person",
[... other properties here ...]
"hidesToPublicFromUnauthedWeb": true,
"hidesCcPublicFromUnauthedWeb": false,
[... other properties here ...]
}
```
GoToSocial respects these flags for incoming posts, but it does not let accounts set this combination of flags for outgoing posts. It may be desirable for other implementers to also prevent users from being able to set this state, as it doesn't make a lot of sense.
## Actor Migration / Aliasing
GoToSocial supports account migration from one instance/server to another through a combination of the `Move` activity, and the Actor Object properties `alsoKnownAs` and `movedTo`.
@ -6,7 +6,7 @@ GoToSocial will also sign all outgoing `GET` and `POST` requests that it makes t
This behavior is the equivalent of Mastodon's [AUTHORIZED_FETCH / "secure mode"](https://docs.joinmastodon.org/admin/config/#authorized_fetch).
GoToSocial uses the [superseriousbusiness/httpsig](https://github.com/superseriousbusiness/httpsign) library (forked from go-fed) for signing outgoing requests, and for parsing and validating the signatures of incoming requests. This library strictly follows the [Cavage http signature RFC](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12), which is the same RFC used by other implementations like Mastodon, Pixelfed, Akkoma/Pleroma, etc. (This RFC has since been superceded by the [httpbis http signature RFC](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures), but this is not yet widely implemented.)
GoToSocial uses the [superseriousbusiness/httpsig](https://codeberg.org/superseriousbusiness/httpsig) library (forked from go-fed) for signing outgoing requests, and for parsing and validating the signatures of incoming requests. This library strictly follows the [Cavage http signature RFC](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12), which is the same RFC used by other implementations like Mastodon, Pixelfed, Akkoma/Pleroma, etc. (This RFC has since been superceded by the [httpbis http signature RFC](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures), but this is not yet widely implemented.)
## Query Parameters
@ -20,11 +20,11 @@ When sending a request, GtS will attempt first *with* query parameters included.
When receiving a request, GtS will attempt to validate the signature first *with* query parameters included. If the signature fails to validate, it will reattempt validation without query parameters included.
See [#894](https://github.com/superseriousbusiness/gotosocial/issues/894) for more details.
See [#894](https://codeberg.org/superseriousbusiness/gotosocial/issues/894) for more details.
## Incoming Requests
GoToSocial request signature validation is implemented in [internal/federation](https://github.com/superseriousbusiness/gotosocial/blob/main/internal/federation/authenticate.go).
GoToSocial request signature validation is implemented in [internal/federation](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/internal/federation/authenticate.go).
GoToSocial will attempt to parse the signature using the following algorithms (in order), stopping at the first success:
@ -36,9 +36,9 @@ ED25519
## Outgoing Requests
GoToSocial request signing is implemented in [internal/transport](https://github.com/superseriousbusiness/gotosocial/blob/main/internal/transport/signing.go).
GoToSocial request signing is implemented in [internal/transport](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/internal/transport/signing.go).
Once https://github.com/superseriousbusiness/gotosocial/issues/2991 is resolved, GoToSocial will use the `(created)` pseudo-header instead of `date`.
Once https://codeberg.org/superseriousbusiness/gotosocial/issues/2991 is resolved, GoToSocial will use the `(created)` pseudo-header instead of `date`.
For now however, when assembling signatures:
@ -82,4 +82,4 @@ For Mastodon, the public key of a user is served as part of that user's Actor re
Remote servers federating with GoToSocial should extract the public key from the `publicKey` field. Then, they should use the `owner` field of the public key to further dereference the full version of the Actor, using a signed `GET` request.
This behavior was introduced as a way of avoiding having remote servers make unsigned `GET` requests to the full Actor endpoint. However, this may change in future as it is not compliant and causes issues. Tracked in [this issue](https://github.com/superseriousbusiness/gotosocial/issues/1186).
This behavior was introduced as a way of avoiding having remote servers make unsigned `GET` requests to the full Actor endpoint. However, this may change in future as it is not compliant and causes issues. Tracked in [this issue](https://codeberg.org/superseriousbusiness/gotosocial/issues/1186).
Much like GoToSocial, this feature is still in pre-v1 beta development. Naming or schemas or methods of approval / rejection may change. We aim to finalize the document by GoToSocial v0.21.0, at which point it can be considered "ready" for other ActivityPub implementers to use.
GoToSocial uses the property `interactionPolicy` on posts, in order to indicate to remote instances what sort of interactions are (conditionally) permitted to be processed and stored by the origin server, for any given post.
The `@context` document for `interactionPolicy` and related objects and properties is at `https://gotosocial.org/ns`.
!!! danger
Interaction policy is an attempt to limit the harmful effects of unwanted replies and other interactions on a user's posts (eg., "reply guys").
However, it is far from being sufficient for this purpose, as there are still many "out-of-band" ways that posts can be distributed or replied to beyond a user's initial wishes or intentions.
For example, a user might create a post with a very strict interaction policy attached to it, only to find that other server softwares do not respect that policy, and users on other instances are having discussions and replying to the post *from their instance's perspective*. The original poster's instance will automatically drop these unwanted interactions from their view, but remote instances may still show them.
Another example: someone might see a post that specifies nobody can reply to it, but screenshot the post, post the screenshot in their own new post, and tag the original post author in as a mention. Alternatively, they might just link to the URL of the post and tag the author in as a mention. In this case, they effectively "reply" to the post by creating a new thread.
For better or worse, GoToSocial can offer only a best-effort, partial, technological solution to what is more or less an issue of social behavior and boundaries.
!!! info "Deprecated `always` and `approvalRequired` properties"
Previous versions of this document used the properties `always` and `approvalRequired`. These are now deprecated in favor of `automaticApproval` and `manualApproval`. GoToSocial versions before v0.20.0 send and receive only these deprecated properties. GoToSocial v0.20.0 sends and receives both the deprecated and the new properties. GoToSocial v0.21.0 onwards uses only the new properties.
## Overview
`interactionPolicy` is an object property attached to the post-like `Object`s `Note`, `Article`, `Question`, etc, with the following format:
- `canLike` is a sub-policy which indicates who is permitted to create a `Like` with the post URI as the `object` of the `Like`.
- `canReply` is a sub-policy which indicates who is permitted to create a post with `inReplyTo` set to the URI/ID of the post.
- `canAnnounce` is a sub-policy which indicates who is permitted to create an `Announce` with the post URI/ID as the `object` of the `Announce`.
And:
- `automaticApproval` denotes ActivityPub URIs/IDs of `Actor`s or `Collection`s of `Actor`s who will receive automated approval from the post author to create + distribute an interaction targeting a post.
- `manualApproval` denotes ActivityPub URIs/IDs of `Actor`s or `Collection`s of `Actor`s who will receive approval from the post author at the author's own discretion, and may not receive approval at all, or may be rejected (see [Requesting, Obtaining, and Validating Approval](#requesting-obtaining-and-validating-approval)).
Valid URI entries in `automaticApproval` and `manualApproval` include:
- the magic ActivityStreams Public URI `https://www.w3.org/ns/activitystreams#Public`
- the URIs of the post creator's `Following` and/or `Followers` collections
Be aware that according to JSON-LD the values of `automaticApproval` and `manualApproval` can be either single strings or arrays of strings. That is, the following are all valid:
- Single string: `"automaticApproval": "https://example.org/users/someone"`
To specify that **nobody** can perform an interaction on a post **except** for its author (who is always permitted), implementations should set the `automaticApproval` array to **just the URI of the post author**, and `manualApproval` can be unset, `null`, or empty.
For example, the following `canLike` value indicates that nobody can `Like` the post it is attached to except for the post author:
Another example. The following `interactionPolicy` on a post by `https://example.org/users/someone` indicates that anyone can like the post, but nobody but the author can reply or announce:
To avoid mischief, GoToSocial makes implicit assumptions about who can/can't interact, even if a policy specifies nobody. See [implicit assumptions](#implicit-assumptions).
## Conflicting / Duplicate Values
In cases where a user is present in a Collection URI, and is *also* targeted explicitly by URI, the **more specific value** takes precedence.
Here, `@someone@example.org` is present in `automaticApproval`, and is also implicitly present in the magic ActivityStreams Public collection in `manualApproval`. In this case, they can always reply, as the `automaticApproval` value is more explicit.
Here, `@someone@example.org` is present in `manualApproval`, but is also implicitly present in the magic ActivityStreams Public collection in `automaticApproval`. In this case everyone can reply without approval, **except** for `@someone@example.org`, who requires approval.
In case the **exact same** URI is present in both `automaticApproval` and `manualApproval`, the **highest level of permission** takes precedence (ie., a URI in `automaticApproval` takes precedence over the same URI in `manualApproval`).
## Default / fallback `interactionPolicy`
When the `interactionPolicy` property is not present at all on a post, or the `interactionPolicy` key is set but its value resolves to `null` or `{}`, implementations can assume the following implicit, default `interactionPolicy` for that post:
As implied by the lack of any `manualApproval` property in any of the sub-policies, the default value for `manualApproval` is an empty array.
This default `interactionPolicy` was designed to reflect the de facto interaction policy of all posts from pre-v0.17.0 GoToSocial, and other ActivityPub server softwares, at the time of writing. That is to say, it is exactly what servers that are not interaction policy aware *already assume* about interaction permissions.
!!! info "Actors can only ever interact with a post they are permitted to see"
Note that even when assuming a default `interactionPolicy` for a post, the **visibility** of a post must still be accounted for by looking at the `to`, `cc`, and/or `audience` properties, to ensure that actors who cannot *see* a post also cannot *interact* with it. Eg., if a post is addressed to followers-only, and the default `interactionPolicy` is assumed, then someone who does not follow the post creator should still *not* be able to see *or* interact with it.
!!! tip
As is standard across AP implementations, implementations will likely still wish to limit `Announce` actities targeting the post to only the author themself if the post is addressed to followers-only.
## Defaults per sub-policy
When an interaction policy is only *partially* defined (eg., only `canReply` is set, `canLike` or `canAnnounce` keys are not set), then implementations should make the following assumptions for each sub-policy in the `interactionPolicy` object that is *undefined*.
!!! tip "Future extensions with different defaults"
Note that **the below list is not exhaustive**, and extensions to `interactionPolicy` may wish to define **different defaults** for other types of interaction.
### `canLike`
If `canLike` is missing on an `interactionPolicy`, or the value of `canLike` is `null` or `{}`, then implementations should assume:
In other words, the default is **anyone who can see the post can announce it**.
## Indicating that verification is required / not required per sub-policy
Because not all servers have implemented interaction policies at the time of writing, it is necessary to provide a method by which implementing servers can indicate that they are both **aware of** and **will enforce** interaction policies as described below in the [Interaction Verification](#interaction-verification) section.
This indication of interaction policy participation is done via a server explicitly setting `interactionPolicy` and its sub-policies on outgoing posts, instead of relying on the defaults described above.
That is, **by setting `interactionPolicy.*` on a post, an instance indicates to other instances that they will enforce validation of interactions for each sub-policy that is explicitly set.**
This means that implementations should always explicitly set all sub-policies on an `interactionPolicy` for which they have implemented interaction controls themselves, and with which they would like other servers to comply.
For example, if a server understands and wishes to enforce the `canLike`, `canReply`, and `canAnnounce` sub-policies (as is the case with GoToSocial), then they should explicitly set those sub-policies on an outgoing post *even when the values do not differ from the implicit defaults*. This allows remote servers to know that the origin server does enforcement, and knows how to handle appropriate `Reject` / `Accept` messages for each sub-policy.
Another example: if a server only implements the `canReply` interaction sub-policy, but not `canLike` or `canAnnounce`, then they should always set `interactionPolicy.canReply`, and leave the other two sub-policies out of the `interactionPolicy` to indicate that they cannot understand or enforce them.
This means of indicating participation in interaction policies through the absence of presence of keys was designed so that the large majority of servers that *do not* set `interactionPolicy` at all, because they have not (yet) implemented it, do not need to change their behavior. Servers that do implement `interactionPolicy` can understand, by the absence of the `interactionPolicy` key on a post, that the origin server is not `interactionPolicy` aware, and behave accordingly.
## Implicit Assumptions
For common-sense safety reasons, GoToSocial makes, and will always apply, two implicit assumptions about interaction policies.
### 1. Mentioned + replied-to actors can always reply
Actors mentioned in, or replied to by, a post should **ALWAYS** be able to reply to that post without requiring approval, regardless of the post visiblity and the `interactionPolicy`, **UNLESS** the post that mentioned or replied to them is itself currently pending approval.
This is to prevent a would-be harasser from mentioning someone in an abusive post, and leaving no recourse to the mentioned user to reply.
As such, when sending out interaction policies, GoToSocial will **ALWAYS** add the URIs of mentioned users to the `canReply.always` array, unless they are already covered by the ActivityStreams magic public URI.
Likewise, when enforcing received interaction policies, GoToSocial will **ALWAYS** behave as though the URIs of mentioned users were present in the `canReply.always` array, even if they weren't.
### 2. An actor can always interact in any way with their own post
**Secondly**, an actor should **ALWAYS** be able to reply to their own post, like their own post, and boost their own post without requiring approval, **UNLESS** that post is itself currently pending approval.
As such, when sending out interaction policies, GoToSocial will **ALWAYS** add the URI of the post author to the `canLike.always`, `canReply.always`, and `canAnnounce.always` arrays, **UNLESS** they are already covered by the ActivityStreams magic public URI.
Likewise, when enforcing received interaction policies, GoToSocial will **ALWAYS** behave as though the URI of the post author themself is present in each `automaticApproval` field, even if it wasn't.
## Examples
Here's some examples of what interaction policies allow users to do.
### 1. Limiting scope of a conversation
In this example, the user `@the_mighty_zork` wants to begin a conversation with the users `@booblover6969` and `@hodor`.
To avoid the discussion being derailed by others, they want replies to their post by users other than the three participants to be permitted only if they're approved by `@the_mighty_zork`.
Furthermore, they want to limit the boosting / `Announce`ing of their post to only their own followers, and to the three conversation participants.
However, anyone should be able to `Like` the post by `@the_mighty_zork`.
This can be achieved with the following `interactionPolicy`, which is attached to a post with visibility level public:
In this example, the user `@the_mighty_zork` wants to write a long solo thread.
They don't mind if people boost and like posts in the thread, but they don't want to get any replies because they don't have the energy to moderate the discussion; they just want to vent by throwing their thoughts out there.
This can be achieved by setting the following `interactionPolicy` on every post in the thread:
Each subsequent reply in a conversation will have its own interaction policy, chosen by the user who created the reply. In other words, the entire *conversation* or *thread* is not controlled by one `interactionPolicy`, but the policy can differ for each subsequent post in a thread, as set by the post author.
Unfortunately, this means that even with `interactionPolicy` in place, the scope of a thread can inadvertently widen beyond the intention of the author of the first post in the thread.
For instance, in [example 1](#example-1---limiting-scope-of-a-conversation) above, `@the_mighty_zork` specifies in the first post a `canReply.always` value of
```json
[
"https://example.org/users/the_mighty_zork",
"https://example.org/users/booblover6969",
"https://example.org/users/hodor"
]
```
In a subsequent reply, either accidentally or on purpose `@booblover6969` sets the `canReply.always` value to:
```json
[
"https://www.w3.org/ns/activitystreams#Public"
]
```
This widens the scope of the conversation, as now anyone can reply to `@booblover6969`'s post, and possibly also tag `@the_mighty_zork` in that reply.
To avoid this issue, it is recommended that remote instances prevent users from being able to widen scope (exact mechanism of doing this TBD).
It is also a good idea for instances to consider any interaction with a post-like `Object` that is itself currently pending approval, as also pending approval.
In other words, instances should mark all children interactions below a pending-approval parent as also pending approval, no matter what the interaction policy on the parent would ordinarily allow.
This avoids situations where someone could reply to a post, then, even if their reply is pending approval, they could reply *to their own reply* and have that marked as permitted (since as author, they would normally have [implicit permission to reply](#implicit-assumptions)).
## Interaction Verification
The [interaction policy](#interaction-policy) section described the shape of interaction policies, assumed defaults, and assumptions.
This section describes the enforcement and verification of interaction policies, ie., how servers that set interaction policies should send approval or rejection of a requested/pending interaction, and how other servers can prove that approval to interact with a post has been obtained by the interacter from the interactee.
### Requesting, Obtaining, and Validating Approval
When an actor's URI is in the `manualApproval` array for a type of interaction, **or** their presence in a collection needs to be validated (see [Validating presence in a Followers / Following collection](#validating-presence-in-a-followers--following-collection)), implementations wishing to obtain approval for that actor to interact with a policied post should do the following:
1. Compose the interaction `Activity` (ie., `Like`, `Create` (reply), or `Announce`), as normal.
2. Address the `Activity``to` and `cc` the expected recipients for that `Activity`, as normal.
3. `POST` the `Activity` only to the `Inbox` (or `sharedInbox`) of the author of the post being interacted with.
4. **DO NOT DISTRIBUTE THE ACTIVITY FURTHER THAN THIS AT THIS POINT**.
At this point, the interaction can be considered as *pending approval*, and should not be shown in the replies or likes collections, etc., of the post interacted with.
It may be shown to the user who sent the interaction as a sort of "interaction pending" modal, but ideally it should not be shown to other users who share an instance with that user.
From here, one of three things may happen:
#### Rejection
In this scenario, the server of the author of the post being interacted with sends back a `Reject``Activity` with the interaction URI/ID as the `object` property.
For example, the following json object `Reject`s the attempt of `@someone@somewhere.else.example.org` to reply to a post by `@post_author@example.org`:
If this happens, `@someone@somewhere.else.example.org` (and their instance) should consider the interaction as having been rejected. The instance should delete the activity from its internal storage (ie., database), or otherwise indicate that it's been rejected, and it should not distribute the `Activity` further, or retry the interaction. The server may wish to indicate to the interacter that their interaction was rejected.
#### Nothing
In this scenario, the author of the post being interacted with never sends back a `Reject` or an `Accept``Activity`. In such a case, the interaction is considered "pending" in perpetuity. Instances may wish to implement some kind of cleanup feature, where sent and pending interactions that reach a certain age should be considered expired, and `Rejected` and then removed in the manner gestured towards above.
#### Acceptance
In this scenario, the author of the post being interacted with sends back an `Accept``Activity` with the interaction URI/ID as the `object` property, and a dereferenceable URI of an approval object as the `result` property (see [Approval Objects](#approval-objects)).
For example, the following json object `Accept`s the attempt of `@someone@somewhere.else.example.org` to reply to a post by `@post_author@example.org`:
If this happens, `@someone@somewhere.else.example.org` (and their instance) should consider the interaction as having been approved/accepted by the interactee.
At this point, `somewhere.else.example.org` should once again send out the interaction, with the following differences:
1. This time, include the `result` URI/ID from the `accept` in the `approvedBy` field of the post contained in the `Create` (see [`approvedBy`](#approvedby)).
2. This time, distribute the interaction to **all** of the recipients targed by `to`, `cc`, etc.
!!! note
While it is not strictly necessary, in the above example, actor `https://example.org/users/post_author` addresses the `Accept` activity not just to the interacting actor `https://somewhere.else.example.org/users/someone`, but to their followers collection as well (and, implicitly, to the public). This allows followers of `https://example.org/users/post_author` on other servers to also mark the interaction as accepted, and to show the interaction alongside the interacted-with post, without having to dereference + verify the URI in `approvedBy`.
### Approval Objects
An approval is an extension of a basic ActivityStreams Object, with the type `LikeApproval`, `ReplyApproval`, or `AnnounceApproval`. Each type corresponds to the type of interaction that the particular approval approves.
- `attributedTo`: should be the `Actor` who `Accept`ed an interaction, ie., the *interactee*.
- `object`: should be the *interacting*`Like`, `Announce`, or post-like `Object`.
- `target` (optional): if included, should be the post-like `Object` that was *interacted with*.
!!! info "Approval objects should be dereferenceable"
As a consequence of the validation mechanism (see [Validating `approvedBy`](#validating-approvedby)), instances should make sure that they serve a valid ActivityPub response to dereferences of approval object URIs. If they do not, they inadvertently risk restricting the ability of remote instances to distribute their posts.
### `approvedBy`
`approvedBy` is an additional property added to the `Like`, and `Announce` activities, and any `Object`s considered to be "posts" (`Note`, `Article`, etc).
The presence of `approvedBy` signals that the author of the post targeted by the `Activity` or replied-to by the `Object` has approved/accepted the interaction, and it can now be distributed to its intended audience.
The value of `approvedBy` should be the `result` URI/ID that was sent along in an `Accept` from the interactee, which points towards a dereferenceable approval object.
For example, the following `Announce``Activity` claims, by the presence of `approvedBy`, that it has been `Accept`ed by `@post_author@example.org`:
When receiving an `Activity` or a post-like `Object` with an `approvedBy` value attached to it, remote instances should:
1. Validate that the host/domain of the `approvedBy` URI is equal to the host/domain of the author of the post being interacted with.
2. Dereference the `approvedBy` URI/ID to get the approval object (see [Approval Objects](#approval-objects)).
3. Check the type of the approval to ensure it's the correct one, eg., an `Announce` should have an `approvedBy` URI/ID set on it that points to an `AnnounceApproval`, not a `ReplyApproval` or a `LikeApproval`.
4. Check that the approval has an `attributedTo` value equal to the URI/ID of the actor being interacted with.
5. Check that the approval has an `object` value equal to the `id` of the interaction `Activity` or `Object`.
If the approval cannot be dereferenced, or does not pass validity checks, the interaction should be considered invalid and dropped.
!!! warning
Versions 0.17.x and 0.18.x of GoToSocial did not include a `result` pointing towards an approval type. Instead, the URI/ID of the `Accept` was sent in the `approvedBy` field.
Version 0.18.x of GoToSocial is partially forward-compatible with approval types, since it can validate approval using either a dereferenced `Accept` or a dereferenced approval type, while still sending out an `Accept` URI itself in the `approvedBy` field.
Versions of GoToSocial from 0.19.x upwards will send out an `approvedBy` pointing to an approval type, as described in this document, not an `Accept`.
### Validating presence in a Followers / Following collection
If an `Actor` interacting with an `object` (via `Like`, `inReplyTo`, or `Announce`) is permitted to do that interaction based on their presence in a `Followers` or `Following` collection in the `automaticApproval` field of an interaction policy, then their server **should still wait** for an `Accept` to be received from the server of the target actor, before distributing the interaction more widely with the `approvedBy` property set to the URI/ID of the approval.
This is to prevent scenarios where third servers have to somehow verify the presence of the interacting `Actor` in the `Followers` or `Following` collection of the `Actor` being interacted with. It is simpler to allow the target server to do that verification, and to trust that their approval implicitly agrees that the interacting `Actor` is present in the relevant collection.
Likewise, when receiving an interaction from an `Actor` whose permission to interact matches with one of the `Following` or `Followers` collections in the `automaticApproval` property, the server of the interacted-with `Actor` should ensure that they *always* send out an `Accept` as soon as possible, so that the interacting `Actor` server can send out the `Activity` with the proper proof of acceptance.
This process should bypass the normal "pending approval" stage whereby the server of the `Actor` being interacted with notifies them of the pending interaction, and waits for them to accept or reject, since there is no point notifying an `Actor` of a pending approval that they have already explicitly agreed to. In the GoToSocial codebase in particular, this is called "preapproval".
### Optional behaviors
This section describes optional behaviors that implementers *may* use when sending `Accept` and `Reject` messages, and *should* account for when receiving `Accept` and `Reject` messages.
#### Always send out `Accept`s
Implementers may wish to *always* send out an `Accept` to remote interacters, even when the interaction is implicitly or explicitly permitted by their presence in the `automaticApproval` array. When receiving such an `Accept`, implementations may still want to update their representation of the interaction to include an `approvedBy` URI pointing at an approval. This may be useful later on when handling revocations (TODO).
#### Type hinting: inline `object` property on `Accept` and `Reject`
If desired, implementers may partially expand/inline the `object` property of an `Accept` or `Reject` to hint to remote servers about the type of interaction being `Accept`ed or `Reject`ed. When inlining in this way, the `object`'s `type` and `id` must be defined at a minimum. For example:
#### Set `target` property on `Accept` and `Reject`
If desired, implementers may set the `target` property on outgoing `Accept` or `Reject` activities to the `id` of the post being interacted with, to make it easier for remote servers to understand the shape and relevance of the interaction that's being `Accept`ed or `Reject`ed.
For example, the following json object `Accept`s the attempt of `@someone@somewhere.else.example.org` to reply to a post by `@post_author@example.org` that has the id `https://example.org/users/post_author/statuses/01JJYV141Y5M4S65SC1XCP65NT`:
If desired, the `target` property can also be partially expanded/inlined to type hint about the post that was interacted with. When inlining in this way, the `target`'s `type` and `id` must be defined at a minimum. For example:
GoToSocial sends media attachments in the `attachment` property of posts using the following types:
- `Image` - any image type (webp, jpeg, gif, png, etc).
- `Video` - any video type (mp4, mkv, webm, etc).
- `Audio` - any audio type (mp3, flac, wma, etc).
- `Document` - fallback for any other / unknown type.
Attachments sent from GoToSocial include the MIME `mediaType`, the `url` of the full-sized version of the media file, and the `summary` property, which can be interpreted by remote instance's as a short description / alt text for the attachment.
Types `Image` and `Video` will also include the `http://joinmastodon.org/ns#blurhash` property so that remotes can generate a colorful hash of the image. If an audio file included an embedded cover art image, then the `Audio` type will also include a blurhash. See the [Mastodon blurhash docs](https://docs.joinmastodon.org/spec/activitypub/#blurhash).
`Image` types may also include the `http://joinmastodon.org/ns#focalPoint` property, which will be an array of two floats between -1.0 and 1.0 indicating the x-y coordinates of the image's focal point. See the [Mastondon focalPoint docs](https://docs.joinmastodon.org/spec/activitypub/#focalPoint).
Here's an example of a `Note` with one attachment:
```json
{
"@context": [
"https://www.w3.org/ns/activitystreams",
{
"blurhash": "toot:blurhash",
"focalPoint": {
"@container": "@list",
"@id": "toot:focalPoint"
},
"toot": "http://joinmastodon.org/ns#"
}
],
"type": "Note",
[...],
"attachment": [
{
"blurhash": "LIIE|gRj00WB-;j[t7j[4nWBj[Rj",
"focalPoint": [
-0.5,
0.5
],
"mediaType": "image/jpeg",
"summary": "Black and white image of some 50's style text saying: Welcome On Board",
When receiving posts with attachments from remote instances, it will try to parse any of the four types `Image`, `Video`, `Audio`, or `Document` into media attachments. It doesn't matter which type is used. It will check for `blurhash` and `focalPoint` properties and use these if they are set. It will use the `summary` value as a short description / alt text, falling back to `name` if `summary` is not set.
## Hashtags
GoToSocial users can include hashtags in their posts, which indicate to other instances that that user wishes their post to be grouped together with other posts using the same hashtag, for discovery purposes.
@ -47,6 +98,60 @@ The `href` URL provided by GoToSocial in outgoing tags points to a web URL that
GoToSocial makes no guarantees whatsoever about what the content of the given `text/html` will be, and remote servers should not interpret the URL as a canonical ActivityPub ID/URI property. The `href` URL is provided merely as an endpoint which *might* contain more information about the given hashtag.
## Emojis
GoToSocial uses the `http://joinmastodon.org/ns#Emoji` type to allow users to add custom emoji to their posts.
For example:
```json
{
"@context": [
"https://gotosocial.org/ns",
"https://www.w3.org/ns/activitystreams",
{
"Emoji": "toot:Emoji",
"sensitive": "as:sensitive",
"toot": "http://joinmastodon.org/ns#"
}
],
"type": "Note",
"content": "<p>here's a stinky creature -> :shocked_pikachu:</p>",
The text `:shocked_pikachu:` in the `content` of the above `Note` should be replaced by clients with a small (inline) version of the emoji image, when rendering the `Note` and displaying it to users.
The `updated` and `icon.url` properties of the emoji can be used by remote instances to determine whether their representation of the GoToSocial emoji image is up to date.
The `Emoji` can also be dereferenced at its `id` URI if necessary, so that remotes can check whether their cached version of the emoji metadata is up to date.
By default, GoToSocial sets a 50kb limit on the size of emoji images that can be uploaded and sent out, and a 100kb limit on the size of emoji images that can be federated in, though both of these settings are configurable by users.
GoToSocial can send and receive emoji images of the type `image/png`, `image/jpeg`, `image/gif`, and `image/webp`.
!!! info
Note that the `tag` property can be either an array of objects, or a single object.
### `null` / empty `id` property
Some server softwares like Akkoma include emojis as [anonymous objects](https://www.w3.org/TR/activitypub/#obj-id) on statuses. That is, they set the `id` property to the value `null` to indicate that the emoji cannot be dereferenced at any specific endpoint.
When receiving such emojis, GoToSocial will generate a dummy id for that emoji in its database in the form `https://[host]/dummy_emoji_path?shortcode=[shortcode]`, for example, `https://example.org/dummy_emoji_path?shortcode=shocked_pikachu`.
## Mentions
GoToSocial users can Mention other users in their posts, using the common `@[username]@[domain]` format. For example, if a GoToSocial user wanted to mention user `someone` on instance `example.org`, they could do this by including `@someone@example.org` in their post somewhere.
@ -165,521 +270,9 @@ If `contentMap` has multiple entries, we have no way of determining the intended
## Interaction Policy
GoToSocial uses the property `interactionPolicy` on posts in order to indicate to remote instances what sort of interactions will be (conditionally) permitted for any given post.
GoToSocial uses the property `interactionPolicy` on posts, in order to indicate to remote instances what sort of interactions are (conditionally) permitted to be processed and stored by the origin server, for any given post.
!!! danger
Interaction policy is an attempt to limit the harmful effects of unwanted replies and other interactions on a user's posts (eg., "reply guys").
However, it is far from being sufficient for this purpose, as there are still many "out-of-band" ways that posts can be distributed or replied to beyond a user's initial wishes or intentions.
For example, a user might create a post with a very strict interaction policy attached to it, only to find that other server softwares do not respect that policy, and users on other instances are having discussions and replying to the post *from their instance's perspective*. The original poster's instance will automatically drop these unwanted interactions from their view, but remote instances may still show them.
Another example: someone might see a post that specifies nobody can reply to it, but screenshot the post, post the screenshot in their own new post, and tag the original post author in as a mention. Alternatively, they might just link to the URL of the post and tag the author in as a mention. In this case, they effectively "reply" to the post by creating a new thread.
For better or worse, GoToSocial can offer only a best-effort, partial, technological solution to what is more or less an issue of social behavior and boundaries.
### Overview
`interactionPolicy` is a property attached to the status-like `Object`s `Note`, `Article`, `Question`, etc, with the following format:
- `canLike` indicates who can create a `Like` with the post URI as the `Object` of the `Like`.
- `canReply` indicates who can create a post with `inReplyTo` set to the URI of the post.
- `canAnnounce` indicates who can create an `Announce` with the post URI as the `Object` of the `Announce`.
And:
- `always` is an array of ActivityPub URIs/IDs of `Actor`s or `Collection`s of `Actor`s who do not require an `Accept` in order to distribute an interaction to their followers (more on this below).
- `approvalRequired` is an array of ActivityPub URIs/IDs of `Actor`s or `Collection`s of `Actor`s who can interact, but should wait for an `Accept` before distributing an interaction to their followers.
Valid URI entries in `always` and `approvalRequired` include the magic ActivityStreams Public URI `https://www.w3.org/ns/activitystreams#Public`, the URIs of the post creator's `Following` and/or `Followers` collections, and individual Actor URIs. For example:
GoToSocial makes implicit assumptions about who can/can't interact, even if a policy specifies nobody. See [implicit assumptions](#implicit-assumptions).
An empty array, or a missing or null key, indicates that nobody can do the interaction.
For example, the following `canLike` value indicates that nobody can `Like` the post:
```json
"canLike": {
"always": [],
"approvalRequired": []
},
```
Likewise, a `canLike` value of `null` also indicates that nobody can `Like` the post:
```json
"canLike": null
```
or
```json
"canLike": {
"always": null,
"approvalRequired": null
}
```
And a missing `canLike` value does the same thing:
In cases where a user is present in a Collection URI, and is *also* targeted explicitly by URI, the **more specific value** takes precedence.
For example:
```json
[...],
"canReply": {
"always": [
"https://example.org/users/someone"
],
"approvalRequired": [
"https://www.w3.org/ns/activitystreams#Public"
]
},
[...]
```
Here, `@someone@example.org` is present in the `always` array, and is also implicitly present in the magic ActivityStreams Public collection in the `approvalRequired` array. In this case, they can always reply, as the `always` value is more explicit.
Another example:
```json
[...],
"canReply": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": [
"https://example.org/users/someone"
]
},
[...]
```
Here, `@someone@example.org` is present in the `approvalRequired` array, but is also implicitly present in the magic ActivityStreams Public collection in the `always` array. In this case everyone can reply without approval, **except** for `@someone@example.org`, who requires approval.
In case the **exact same** URI is present in both `always` and `approvalRequired`, the **highest level of permission** takes precedence (ie., a URI in `always` takes precedence over the same URI in `approvalRequired`).
### Implicit Assumptions
GoToSocial makes several implicit assumptions about `interactionPolicy`s.
**Firstly**, users [mentioned](#mentions) in, or replied to by, a post should **ALWAYS** be able to reply to that post without requiring approval, regardless of the post visiblity and the `interactionPolicy`, **UNLESS** the post that mentioned or replied to them is itself currently pending approval.
This is to prevent a would-be harasser from mentioning someone in an abusive post, and leaving no recourse to the mentioned user to reply.
As such, when sending out interaction policies, GoToSocial will **ALWAYS** add the URIs of mentioned users to the `canReply.always` array, unless they are already covered by the ActivityStreams magic public URI.
Likewise, when enforcing received interaction policies, GoToSocial will **ALWAYS** behave as though the URIs of mentioned users were present in the `canReply.always` array, even if they weren't.
**Secondly**, a user should **ALWAYS** be able to reply to their own post, like their own post, and boost their own post without requiring approval, **UNLESS** that post is itself currently pending approval.
As such, when sending out interaction policies, GoToSocial will **ALWAYS** add the URI of the post author to the `canLike.always`, `canReply.always`, and `canAnnounce.always` arrays, unless they are already covered by the ActivityStreams magic public URI.
Likewise, when enforcing received interaction policies, GoToSocial will **ALWAYS** behave as though the URI of the post author is present in these `always` arrays, even if it wasn't.
### Defaults
When the `interactionPolicy` property is not present at all on a post, GoToSocial assumes a default `interactionPolicy` for that post appropriate to the visibility level of the post, and the post author.
For a **public** or **unlocked** post by `@someone@example.org`, the default `interactionPolicy` is:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
}
},
[...]
}
```
For a **followers-only** post by `@someone@example.org`, the assumed `interactionPolicy` is:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://example.org/users/someone",
"https://example.org/users/someone/followers",
[...URIs of any mentioned users...]
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://example.org/users/someone",
"https://example.org/users/someone/followers",
[...URIs of any mentioned users...]
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://example.org/users/someone"
],
"approvalRequired": []
}
},
[...]
}
```
For a **direct** post by `@someone@example.org`, the assumed `interactionPolicy` is:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://example.org/users/someone",
[...URIs of any mentioned users...]
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://example.org/users/someone",
[...URIs of any mentioned users...]
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://example.org/users/someone"
],
"approvalRequired": []
}
},
[...]
}
```
### Example 1 - Limiting scope of a conversation
In this example, the user `@the_mighty_zork` wants to begin a conversation with the users `@booblover6969` and `@hodor`.
To avoid the discussion being derailed by others, they want replies to their post by users other than the three participants to be permitted only if they're approved by `@the_mighty_zork`.
Furthermore, they want to limit the boosting / `Announce`ing of their post to only their own followers, and to the three conversation participants.
However, anyone should be able to `Like` the post by `@the_mighty_zork`.
This can be achieved with the following `interactionPolicy`, which is attached to a post with visibility level public:
In this example, the user `@the_mighty_zork` wants to write a long solo thread.
They don't mind if people boost and like posts in the thread, but they don't want to get any replies because they don't have the energy to moderate the discussion; they just want to vent by throwing their thoughts out there.
This can be achieved by setting the following `interactionPolicy` on every post in the thread:
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://example.org/users/the_mighty_zork"
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
}
},
[...]
}
```
Here, anyone is allowed to like or boost, but nobody is permitted to reply (except `@the_mighty_zork` themself).
### Example 3 - Completely open
In this example, `@the_mighty_zork` wants to write a completely open post that can be replied to, boosted, or liked by anyone who can see it (ie., the default behavior for unlocked and public posts):
```json
{
[...],
"interactionPolicy": {
"canLike": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canReply": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
},
"canAnnounce": {
"always": [
"https://www.w3.org/ns/activitystreams#Public"
],
"approvalRequired": []
}
},
[...]
}
```
### Requesting, Obtaining, and Validating Approval
When a user's URI is in the `approvalRequired` array for a type of interaction, and that user wishes to obtain approval to distribute an interaction, they should do the following:
1. Compose the interaction `Activity` (ie., `Like`, `Create` (reply), or `Announce`), as normal.
2. Address the `Activity``to` and `cc` the expected recipients for that `Activity`, as normal.
3. `POST` the `Activity` only to the `Inbox` (or `sharedInbox`) of the author of the post being interacted with.
4. **DO NOT DISTRIBUTE THE ACTIVITY FURTHER THAN THIS AT THIS POINT**.
At this point, the interaction can be considered as pending approval, and should not be shown in the replies or likes collections, etc., of the post interacted with.
It may be shown to the user who sent the interaction as a sort of "interaction pending" modal, but ideally it should not be shown to other users who share an instance with that user.
From here, one of three things may happen:
#### Rejection
In this scenario, the author of the post being interacted with sends back a `Reject``Activity` with the URI/ID of the interaction `Activity` as the `Object` property.
For example, the following json object `Reject`s the attempt of `@someone@somewhere.else.example.org` to reply to a post by `@post_author@example.org`:
If this happens, `@someone@somewhere.else.example.org` (and their instance) should consider the interaction as having been rejected. The instance should delete the activity from its internal storage (ie., database), or otherwise indicate that it's been rejected, and it should not distribute the `Activity` further, or retry the interaction.
#### Nothing
In this scenario, the author of the post being interacted with never sends back a `Reject` or an `Accept``Activity`. In such a case, the interaction is considered "pending" in perpetuity. Instances may wish to implement some kind of cleanup feature, where sent and pending interactions that reach a certain age should be considered expired, and `Rejected` and then removed in the manner gestured towards above.
#### Acceptance
In this scenario, the author of the post being interacted with sends back an `Accept``Activity` with the URI/ID of the interaction `Activity` as the `Object` property.
For example, the following json object `Accept`s the attempt of `@someone@somewhere.else.example.org` to reply to a post by `@post_author@example.org`:
If this happens, `@someone@somewhere.else.example.org` (and their instance) should consider the interaction as having been approved / accepted. The instance can then feel free to distribute the interaction `Activity` to all of the recipients targed by `to`, `cc`, etc, with the additional property `approvedBy` ([see below](#approvedby)).
### Validating presence in a Followers / Following collection
If an `Actor` interacting with an `Object` (via `Like`, `inReplyTo`, or `Announce`) is permitted to do that interaction based on their presence in a `Followers` or `Following` collection in the `always` field of an interaction policy, then their server should *still* wait for an `Accept` to be received from the server of the target account, before distributing the interaction more widely with the `approvedBy` property set to the URI of the `Accept`.
This is to prevent scenarios where third servers have to somehow verify the presence of the interacting `Actor` in the `Followers` or `Following` collection of the `Actor` being interacted with. It is simpler to allow the target server to do that verification, and to trust that their `Accept` implicitly agrees that the interacting `Actor` is present in the relevant collection.
Likewise, when receiving an interaction from an `Actor` whose permission to interact matches with one of the `Following` or `Followers` collections in the `always` property, the server of the interacted-with `Actor` should ensure that they *always* send out an `Accept` as soon as possible, so that the interacting `Actor` server can send out the `Activity` with the proper proof of acceptance.
This process should bypass the normal "pending approval" stage whereby the server of the `Actor` being interacted with notifies them of the pending interaction, and waits for them to accept or reject, since there is no point notifying an `Actor` of a pending approval that they have already explicitly agreed to. In the GoToSocial codebase in particular, this is called "preapproval".
### `approvedBy`
`approvedBy` is an additional property added to the `Like`, and `Announce` activities, and any `Object`s considered to be "posts" (`Note`, `Article`, etc).
The presence of `approvedBy` signals that the author of the post targeted by the `Activity` or replied-to by the `Object` has approved/accepted the interaction, and it can now be distributed to its intended audience.
The value of `approvedBy` should be the URI of the `Accept``Activity` created by the author of the post being interacted with.
For example, the following `Announce``Activity` indicates, by the presence of `approvedBy`, that it has been `Accept`ed by `@post_author@example.org`:
When receiving an `Activity` with an `approvedBy` value attached to it, remote instances should dereference the URI value of the field to get the `Accept``Activity`.
They should then validate that the `Accept``Activity` has an `object` value equal to the `id` of the interaction `Activity` or `Object`, and an `actor` value equal to the author of the post being interacted with.
Moreover, they should ensure that the URL host/domain of the dereferenced `Accept` is equal to the URL host/domain of the author of the post being interacted with.
If the `Accept` cannot be dereferenced, or does not pass validity checks, the interaction should be considered invalid and dropped.
As a consequence of this validadtion mechanism, instances should make sure that they serve a valid ActivityPub Object in response to dereferences of `Accept` URIs that pertain to an `interactionPolicy`. If they do not, they inadvertently risk restricting the ability of remote instances to distribute their posts.
### Subsequent Replies / Scope Widening
Each subsequent reply in a conversation will have its own interaction policy, chosen by the user who created the reply. In other words, the entire *conversation* or *thread* is not controlled by one `interactionPolicy`, but the policy can differ for each subsequent post in a thread, as set by the post author.
Unfortunately, this means that even with `interactionPolicy` in place, the scope of a thread can inadvertently widen beyond the intention of the author of the first post in the thread.
For instance, in [example 1](#example-1---limiting-scope-of-a-conversation) above, `@the_mighty_zork` specifies in the first post a `canReply.always` value of
```json
[
"https://example.org/users/the_mighty_zork",
"https://example.org/users/booblover6969",
"https://example.org/users/hodor"
]
```
In a subsequent reply, either accidentally or on purpose `@booblover6969` sets the `canReply.always` value to:
```json
[
"https://www.w3.org/ns/activitystreams#Public"
]
```
This widens the scope of the conversation, as now anyone can reply to `@booblover6969`'s post, and possibly also tag `@the_mighty_zork` in that reply.
To avoid this issue, it is recommended that remote instances prevent users from being able to widen scope (exact mechanism of doing this TBD).
It is also a good idea for instances to consider any interaction with a post- or status-like `Object` that is itself currently pending approval, as also pending approval.
In other words, instances should mark all children interactions below a pending-approval parent as also pending approval, no matter what the interaction policy on the parent would ordinarily allow.
This avoids situations where someone could reply to a post, then, even if their reply is pending approval, they could reply *to their own reply* and have that marked as permitted (since as author, they would normally have [implicit permission to reply](#implicit-assumptions)).
For more details on this, see the separate [interaction policy](./interaction_policy.md) document.
## Polls
@ -905,7 +498,7 @@ Now, `remote_1` boosts/reblogs a post from a third account, `remote_2`, residing
`local_account` does not follow `remote_2`, and neither does anybody else on `our.server`, which means that `our.server` has not seen this post by `remote_2` before.


What GoToSocial will do now, is 'dereference' the post by `remote_2` to check if it is part of a thread and, if so, whether any other parts of the thread can be obtained.
@ -20,7 +20,7 @@ You can find more detail on system requirements below, but in short you should a
For a small instance (1-20 active users), GoToSocial will likely hover consistently between 250MB and 350MB of RAM usage once the internal caches are hydrated:


In the graph above you can see that RAM usage spikes during periods of load. This happens, for example, when when a status gets boosted by someone with many followers, or when the embedded `ffmpeg` binary is decoding or reencoding media files into thumbnails (especially larger video files).
@ -55,7 +55,7 @@ For media storage, including [storage of remote media files in the cache](../adm
### Single-board Computers
GoToSocial's light system requirements means that it runs pretty well on decently-specced single-board computers. If running on a single-board computer, you should ensure that GoToSocial is using a USB drive (preferably an SSD) to store its database files and media, not SD card storage, since the latter tends to be too slow to run a database on.
GoToSocial's light system requirements means that it runs pretty well on decently-specced single-board computers. If running on a single-board computer, you should ensure that GoToSocial is using a USB drive (preferably an SSD) to store its database files and media, not SD card storage, since the latter tends to be too slow to run a database on and can easily get corrupted with write-heavy workloads.
### VPS
@ -65,14 +65,16 @@ If you decide to use a VPS instead, you can spin yourself up something cheap wit
[Greenhost](https://greenhost.net) is also great: it has zero CO2 emissions, but is a bit more costly. Their 1GB, 1-cpu VPS works great for a single-user or small instance.
!!! warning "Cloud storage volumes"
Not all cloud VPS storage offerings are equal, and just because something claims to be backed by an SSD doesn't mean that it will necessarily be suitable to run a GoToSocial instance.
The [performance of Hetzner Cloud Volumes](https://codeberg.org/superseriousbusiness/gotosocial/issues/2471#issuecomment-1891098323) is not guaranteed and seems to have very volatile latency. This will result in your GoToSocial instance performing poorly.
!!! danger "Oracle Free Tier"
[Oracle Cloud Free Tier](https://www.oracle.com/cloud/free/) servers are not suitable for a GoToSocial deployment if you intend to federate with more than a handful of other instances and users.
GoToSocial admins running on Oracle Cloud Free Tier have reported that their instances become extremely slow or unresponsive during periods of moderate load. This is most likely due to memory or storage latency, which causes even simple database queries to take a long time to run.
!!! danger "Hetzner Cloud Volume"
The [performance of Hetzner Cloud Volumes](https://github.com/superseriousbusiness/gotosocial/issues/2471#issuecomment-1891098323) is not guaranteed and seems to have very volatile latency. You're going to have a bad time running your database on those, with extremely poor query performance for even the most basic operations. Before filing performance issues against GoToSocial, make sure the problems reproduce with local storage.
### Distribution system requirements
Please make sure to check on your distribution system requirments, especially memory. Many distributions have baseline requirements and running them on a system that doesn't meet them will cause problems without further tuning and tweaking on your part.
@ -99,13 +101,15 @@ GoToSocial supports both SQLite and Postgres as database drivers. Though it is p
SQLite is the default driver and it's been shown to work brilliantly for instances in the range of 1-30 users (or maybe more).
!!! danger "SQLite on networked storage"
Don't put your SQLite database on remote storage, whether that's NFS/Samba, iSCSI volumes, things like Ceph/Gluster or your cloud provider's network volume storage solution.
See [SQLite on networked storage](../advanced/sqlite-networked-storage.md) for further information.
If you're planning on hosting more people than this on an instance, you may wish to use Postgres instead, as it offers the possibility of database clustering and redundancy, at the cost of some complexity.
Regardless of which database driver you choose, for proper performance they should be run on fast storage that operates with low and stable latency. It is possible to run databases on network attached storage, but this adds variable latency and network congestion to the mix, as well as potential I/O contention on the origin storage.
!!! danger "Cloud Storage Volumes"
Not all cloud VPS storage offerings are equal, and just because something claims to be backed by an SSD doesn't mean that it will necessarily be suitable to run a GoToSocial instance on. Please see the [Server/VPS section](#vps) section below.
!!! tip
Please [backup your database](../admin/backup_and_restore.md). The database contains encryption keys for the instance and any user accounts. You won't be able to federate again from the same domain if you lose these keys!
@ -145,13 +149,13 @@ If you can't leave `443` and `80` open on the machine, don't worry! You can conf
## Clustering / multi-node deployments
GoToSocial does not support [clustering or any form of multi-node deployment](https://github.com/superseriousbusiness/gotosocial/issues/1749).
GoToSocial does not support [clustering or any form of multi-node deployment](https://codeberg.org/superseriousbusiness/gotosocial/issues/1749).
Though multiple GtS instances can use the same Postgres database and either shared local storage or the same object bucket, GtS relies on a lot of internal caching to keep things fast. There is no mechanism for synchronising these caches between instances. Without it, you'll get all kinds of odd and inconsistent behaviour. Don't do this!
## Tuning
Aside from the many instance tuning options present in the [example config file](https://github.com/superseriousbusiness/gotosocial/blob/main/example/config.yaml) you can do additional tuning on the machine your GoToSocial instance is running on.
Aside from the many instance tuning options present in the [example config file](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/example/config.yaml) you can do additional tuning on the machine your GoToSocial instance is running on.
Use `wget` to download the latest [docker-compose.yaml](https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/example/docker-compose/docker-compose.yaml) example, which we'll customize for our needs:
Use `wget` to download the latest [docker-compose.yaml](https://codeberg.org/superseriousbusiness/gotosocial/raw/branch/main/example/docker-compose/docker-compose.yaml) example, which we'll customize for our needs:
@ -42,10 +42,10 @@ If desired, update the GoToSocial Docker image tag to the version of GtS you wan
* `latest`: the default. This points to the latest stable release of GoToSocial.
* `snapshot`: points to whatever code is currently on the main branch. Not guaranteed to be stable, and may often be broken. Use with caution.
* `vX.Y.Z`: release tag. This points to a specific, stable, release of GoToSocial.
* `X.Y.Z`: release tag. This points to a specific, stable, release of GoToSocial.
!!! tip
Both the `latest` and `snapshot` tags are moving tags, whereas the `vX.Y.Z` tags are immutable. The result of pulling a moving tag might change from day to day. `latest` on one system might not be the same `latest` on a different system. It's recommended to use the `vX.Y.Z` tags instead so you always know exactly which version of GoToSocial you're running. The list of releases can be found [right here](https://github.com/superseriousbusiness/gotosocial/releases), with the newest release at the top.
Both the `latest` and `snapshot` tags are moving tags, whereas the `X.Y.Z` tags are immutable. The result of pulling a moving tag might change from day to day. `latest` on one system might not be the same `latest` on a different system. It's recommended to use the `X.Y.Z` tags instead so you always know exactly which version of GoToSocial you're running. The list of releases can be found [right here](https://codeberg.org/superseriousbusiness/gotosocial/releases), with the newest release at the top.
### Host
@ -91,6 +91,32 @@ If you want to use [LetsEncrypt](../../configuration/tls.md) for TLS certificate
For help translating variable names from the config.yaml file to environment variables, refer to the [configuration section](../../configuration/index.md#environment-variables).
### Wazero Compilation Cache (optional)
On startup, GoToSocial compiles embedded WebAssembly `ffmpeg` and `ffprobe` binaries into [Wazero](https://wazero.io/)-compatible modules, which are used for media processing without requiring any external dependencies.
To speed up startup time of GoToSocial, you can cache the compiled modules between restarts so that GoToSocial doesn't have to compile them on every startup from scratch.
If you'd like to do this in your Docker container, first create a `.cache` directory in your working folder to store the modules:
```bash
mkdir -p ~/gotosocial/.cache
```
Then, uncomment the second volume in the docker-compose.yaml file by removing the leading `#` symbol, so that instead of
```yaml
#- ~/gotosocial/.cache:/gotosocial/.cache
```
it reads
```yaml
- ~/gotosocial/.cache:/gotosocial/.cache
```
This will instruct Docker to mount the `~/gotosocial/.cache` directory at `/gotosocial/.cache` inside the Docker container.
## Start GoToSocial
With those small changes out of the way, you can now start GoToSocial with the following command:
Now, download the latest GoToSocial release archive corresponding to the operating system and architecture you're running on.
!!! tip
You can find the list of releases [right here](https://github.com/superseriousbusiness/gotosocial/releases), arranged with the newest release at the top.
You can find the list of releases [right here](https://codeberg.org/superseriousbusiness/gotosocial/releases), arranged with the newest release at the top.
For example, to download a version for running on 64-bit Linux:
@ -63,8 +63,6 @@ You'll probably need to change the following settings:
- Set `host` to whatever hostname you're going to be running the server on (eg., `example.org`).
- Set `port` to `443`.
- Set `db-type` to `sqlite`.
- Set `db-address` to `sqlite.db`.
- Set `storage-local-base-path` to the storage directory you created above (eg., `/gotosocial/storage`).
- Set `letsencrypt-enabled` to `true`.
- Set `letsencrypt-cert-dir` to the certificate storage directory you created above (eg., `/gotosocial/storage/certs`).
@ -123,7 +121,7 @@ Then make them the owner of your GoToSocial installation since they will need to
sudo chown -R gotosocial:gotosocial /gotosocial
```
You can find a `gotosocial.service` file in the `example` folder on [github](https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/example/gotosocial.service) or your installation.
You can find a `gotosocial.service` file in the `example` folder on [our repository](https://codeberg.org/superseriousbusiness/gotosocial/raw/branch/main/example/gotosocial.service) or your installation.
Copy it to `/etc/systemd/system/gotosocial.service`:
GoToSocial can be installed in a number of different ways. We publish official binary releases as well as container images. A number of third-party packages are maintained by different distributions and some people have created additional deployment tooling to make it easy to deploy GoToSocial yourself.
GoToSocial can be installed in a number of different ways. We publish official binary releases as well as container images.
## Binary releases
A number of third-party packages are maintained by different distributions, and some people have created additional deployment tooling to make it easy to deploy GoToSocial yourself.
We publish binary builds for Linux to [our GitHub project](https://github.com/superseriousbusiness/gotosocial/releases):
* 32-bit Intel/AMD (i386/x86)
* 64-bit Intel/AMD (amd64/x86_64)
* 32-bit ARM (v6 and v7)
* 64-bit ARM64
For FreeBSD we publish:
* 64-bit Intel/AMD (amd64/x86_64)
## Containers
We also publish container images [on the Docker Hub](https://hub.docker.com/r/superseriousbusiness/gotosocial).
Containers are released for the same Linux platforms as our binary releases, with the exception of 32-bit Intel/AMD.
## Snapshots
We publish snapshot binary builds and Docker images of whatever is currently on main.
We always recommend using a stable release instead, but if you want to live on the edge (at your own risk!) then see the [snapshots](https://github.com/superseriousbusiness/gotosocial#snapshots) section on our GitHub repo for more information.
## Third-party
Some folks have created distribution packages for GoToSocial or additional tooling to aid in installing GoToSocial.
### Distribution packages
These packages are not maintained by GoToSocial, so please direct questions and issues to the repository maintainers (and donate to them!).
You can deploy your own instance of GoToSocial with the help of:
- [YunoHost GoToSocial Packaging](https://github.com/YunoHost-Apps/gotosocial_ynh) by [OniriCorpe](https://github.com/OniriCorpe).
- [Ansible Playbook (MASH)](https://github.com/mother-of-all-self-hosting/mash-playbook): The playbook supports a many services, including GoToSocial. [Documentation](https://github.com/mother-of-all-self-hosting/mash-playbook/blob/main/docs/services/gotosocial.md)
- GoToSocial Helm Charts:
- [GoToSocial Helm Chart](https://github.com/fSocietySocial/charts/tree/main/charts/gotosocial) by [0hlov3](https://github.com/0hlov3).
In your GoToSocial config turn off Lets Encrypt by setting `letsencrypt-enabled` to `false`.
If you we running GoToSocial on port 443, change the `port` value back to the default `8080`.
If you are running GoToSocial on port 443, change the `port` value back to the default `8080`.
If the reverse proxy will be running on the same machine, set the `bind-address` to `"localhost"` so that the GoToSocial server is only accessible via loopback. Otherwise it may be possible to bypass your proxy by connecting to GoToSocial directly, which might be undesirable.
@ -73,7 +73,7 @@ example.org {
# The actual proxy configuration to port 8080 (unless you've chosen another port number)
reverse_proxy * http://127.0.0.1:8080 {
# Flush immediatly, to prevent buffered response to the client
# Flush immediately, to prevent buffered response to the client
@ -41,3 +41,7 @@ We have guides available for the following servers:
When using a reverse-proxy, special care must be taken to allow WebSockets to work too. This is necessary as many client applications use WebSockets to stream your timeline. WebSockets is not used as part of federation.
Make sure you read the [WebSocket](websocket.md) documentation and configure your reverse proxy accordingly.
## Trusted Proxies
When using a reverse-proxy, you may run into issues with rate limiting and `trusted-proxies`. Check the [trusted proxies](../../configuration/trusted_proxies.md) documentation if you have any problems.
GoToSocial uses the secure [WebSocket protocol](https://en.wikipedia.org/wiki/WebSocket) (aka `wss`) to allow for streaming updates of statuses and notifications via client apps like Semaphore.
GoToSocial uses the secure [WebSocket protocol](https://en.wikipedia.org/wiki/WebSocket) (aka `wss`) to allow for streaming updates of statuses and notifications via client apps like Pinafore.
In order to use this functionality, you need to ensure that whatever proxy you've configured GoToSocial to run behind allows WebSocket connections through.
Some files were not shown because too many files have changed in this diff
Show more