diff options
Diffstat (limited to 'docs/getting_started')
-rw-r--r-- | docs/getting_started/advanced.md | 447 | ||||
-rw-r--r-- | docs/getting_started/index.md | 75 | ||||
-rw-r--r-- | docs/getting_started/installation/container.md | 123 | ||||
-rw-r--r-- | docs/getting_started/installation/index.md | 14 | ||||
-rw-r--r-- | docs/getting_started/installation/metal.md | 123 | ||||
-rw-r--r-- | docs/getting_started/releases.md | 40 | ||||
-rw-r--r-- | docs/getting_started/reverse_proxy/apache-httpd.md | 250 | ||||
-rw-r--r-- | docs/getting_started/reverse_proxy/caddy.md | 108 | ||||
-rw-r--r-- | docs/getting_started/reverse_proxy/index.md | 43 | ||||
-rw-r--r-- | docs/getting_started/reverse_proxy/nginx.md | 186 | ||||
-rw-r--r-- | docs/getting_started/reverse_proxy/websocket.md | 43 | ||||
-rw-r--r-- | docs/getting_started/tracing.md | 44 | ||||
-rw-r--r-- | docs/getting_started/user_creation.md | 50 |
13 files changed, 1546 insertions, 0 deletions
diff --git a/docs/getting_started/advanced.md b/docs/getting_started/advanced.md new file mode 100644 index 000000000..ecd73fdbe --- /dev/null +++ b/docs/getting_started/advanced.md @@ -0,0 +1,447 @@ +# Advanced + +Advanced configuration options for GoToSocial. + +## Can I host my instance at `fedi.example.org` but have just `@example.org` in my username? + +Yes, you can! This is useful when you have something like a personal page or blog at `example.org`, but you also want your fediverse account to have `example.org` in it to avoid confusing people, or just because it looks nicer than `fedi.example.org`. + +Please note that you need to do this *BEFORE RUNNING GOTOSOCIAL* for the first time, or things will likely break. + +An additional thing to keep in mind is that there is no good way for applications to detect if you're running this style of deployment. Therefor you should recommend that folks use `fedi.example.org` as the instance to login to in any client application. + +Some applications do have heuristics built-in to try and detect this situation and make login from either domain possible. That heuristic relies on `/api/v1/instance` or `/api/v1/apps` not responding on `example.org`. When that happens they'll do a fallback lookup by requesting `example.org/.well-known/host-meta`. You need to ensure that this endpoint is properly redirected to `fedi.example.org` as shown in our examples below. It is crucial you don't redirect `/api` or any of its subpaths from `example.org` to `fedi.example.org`, but only the well-known endpoints, to not break this heuristic. + +### Step 1: Configure GoToSocial + +This step is easy. + +In the settings, GoToSocial differentiates between `host`--the address at which your instance is accessible--and `account-domain`--which is the domain you want to show in accounts. + +Behold, from the example config.yaml file: + +```yaml +# String. Hostname that this server will be reachable at. Defaults to localhost for local testing, +# but you should *definitely* change this when running for real, or your server won't work at all. +# DO NOT change this after your server has already run once, or you will break things! +# Examples: ["gts.example.org","some.server.com"] +# Default: "localhost" +host: "localhost" + +# String. Domain to use when federating profiles. This is useful when you want your server to be at +# eg., "gts.example.org", but you want the domain on accounts to be "example.org" because it looks better +# or is just shorter/easier to remember. +# +# To make this setting work properly, you need to redirect requests at "example.org/.well-known/webfinger" +# to "gts.example.org/.well-known/webfinger" so that GtS can handle them properly. +# +# You should also redirect requests at "example.org/.well-known/nodeinfo" in the same way. +# +# You should also redirect requests at "example.org/.well-known/host-meta" in the same way. This endpoint is used by a number of clients to discover the API endpoint to use when the host and account domain are different. +# +# An empty string (ie., not set) means that the same value as 'host' will be used. +# +# DO NOT change this after your server has already run once, or you will break things! +# +# Please read the appropriate section of the installation guide before you go messing around with this setting: +# https://docs.gotosocial.org/installation_guide/advanced/#can-i-host-my-instance-at-fediexampleorg-but-have-just-exampleorg-in-my-username +# +# Examples: ["example.org","server.com"] +# Default: "" +account-domain: "" +``` + +The first value, `host`, is simple. In our scenario of wanting to run the GtS instance at `fedi.example.org`, this should be set to, yep, `fedi.example.org`. + +The second value, `account-domain` should be set to `example.org`, to indicate that that's the domain we want accounts to be displayed with. + +IMPORTANT: `account-domain` must be a *parent domain* of `host`, and `host` must be a *subdomain* of `account-domain`. So if your `host` is `fedi.example.org`, your `account-domain` cannot be `somewhere.else.com` or `example.com`, it **has to be** `example.org`. + +### Step 2: Redirect from `example.org` to `fedi.example.org` + +The next step is more difficult: we need to ensure that when remote instances search for the user `@user@example.org` via webfinger, they end up being pointed towards `fedi.example.org`, where our instance is actually hosted. + +Of course, we don't want to redirect *all* requests from `example.org` to `fedi.example.org` because that negates the purpose of having a separate domain in the first place, so we need to be specific. + +In the config.yaml above, there are three endpoints mentioned, all of which we need to redirect: `/.well-known/webfinger`, `/.well-known/nodeinfo` and `/.well-known/host-meta`. + +Assuming we have an [nginx](https://nginx.org) reverse proxy running on `example.org`, we can get the redirect behavior we want by adding the following to the nginx config for `example.org`: + +```nginx +http { + server { + listen 80; + listen [::]:80; + server_name example.org; + + location /.well-known/webfinger { + rewrite ^.*$ https://fedi.example.org/.well-known/webfinger permanent; + } + + location /.well-known/host-meta { + rewrite ^.*$ https://fedi.example.org/.well-known/host-meta permanent; + } + + location /.well-known/nodeinfo { + rewrite ^.*$ https://fedi.example.org/.well-known/nodeinfo permanent; + } + + # The rest of our nginx config ... + } +} +``` + +The above configuration [rewrites](https://www.nginx.com/blog/creating-nginx-rewrite-rules/) queries to `example.org/.well-known/webfinger`, `example.org/.well-known/nodeinfo` and `example.org/.well-known/host-meta` to their `fedi.example.org` counterparts while preserving any query arguments, making it easier to follow the redirect. + +If `example.org` is running on [Traefik](https://doc.traefik.io/traefik/), we could use labels similar to the following to setup the redirect. + +```docker + myservice: + image: foo + # Other stuff + labels: + - 'traefik.http.routers.myservice.rule=Host(`example.org`)' + - 'traefik.http.middlewares.myservice-gts.redirectregex.permanent=true' + - 'traefik.http.middlewares.myservice-gts.redirectregex.regex=^https://(.*)/.well-known/(webfinger|nodeinfo|host-meta)$$' + - 'traefik.http.middlewares.myservice-gts.redirectregex.replacement=https://fedi.$${1}/.well-known/$${2}' + - 'traefik.http.routers.myservice.middlewares=myservice-gts@docker' +``` + +### Step 3: What now? + +Once you've done steps 1 and 2, proceed as normal with the rest of your GoToSocial installation. + +### Supplemental: how does this work? + +With the configuration we put in place in the steps above, when someone from another instance looks up `@user@example.org`, their instance will perform a webfinger request to `example.org/.well-known/webfinger?resource:acct=user@example.org` in order to discover a link to an ActivityPub representation of that user's account. They will then be redirected to `https://fedi.example.org/.well-known/webfinger?resource:acct=user@example.org`, and their query will be resolved. + +The webfinger response returned by GoToSocial (and indeed Mastodon, and other ActivityPub implementations) contains the desired account domain in the `subject` part of the response, and provides links to aliases that should be used to query the account. + +Here's an example of this working for the `superseriousbusiness.org` GoToSocial instance, which is hosted at `gts.superseriousbusiness.org`. + +Curl query: + +```bash +curl -v 'https://superseriousbusiness.org/.well-known/webfinger?resource=acct:@gotosocial@superseriousbusiness.org' +``` + +Response: + +```text +> GET /.well-known/webfinger?resource=acct:@gotosocial@superseriousbusiness.org HTTP/2 +> Host: superseriousbusiness.org +> user-agent: curl/7.68.0 +> accept: */* +> +< HTTP/2 301 +< content-type: text/html +< date: Thu, 17 Nov 2022 11:10:39 GMT +< location: https://gts.superseriousbusiness.org/.well-known/webfinger?resource=acct:@gotosocial@superseriousbusiness.org +< server: nginx/1.20.1 +< content-length: 169 +< +<html> +<head><title>301 Moved Permanently</title></head> +<body> +<center><h1>301 Moved Permanently</h1></center> +<hr><center>nginx/1.20.1</center> +</body> +</html> + +``` + +If we follow the redirect and make a query to the specified `location` as follows: + +```bash +curl -v 'https://gts.superseriousbusiness.org/.well-known/webfinger?resource=acct:@gotosocial@superseriousbusiness.org' +``` + +Then we get the following response: + +```json +{ + "subject": "acct:gotosocial@superseriousbusiness.org", + "aliases": [ + "https://gts.superseriousbusiness.org/users/gotosocial", + "https://gts.superseriousbusiness.org/@gotosocial" + ], + "links": [ + { + "rel": "http://webfinger.net/rel/profile-page", + "type": "text/html", + "href": "https://gts.superseriousbusiness.org/@gotosocial" + }, + { + "rel": "self", + "type": "application/activity+json", + "href": "https://gts.superseriousbusiness.org/users/gotosocial" + } + ] +} +``` + +In the above response, note that the `subject` of the response contains the desired account-domain of `superseriousbusiness.org`, whereas the links contain the actual host value of `gts.superseriousbusiness.org`. + +## Can I make my GoToSocial instance use a proxy (http, https, socks5) for outgoing requests? + +Yes! GoToSocial supports canonical environment variables for doing this: `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` (or the lowercase versions thereof). `HTTPS_PROXY` takes precedence over `HTTP_PROXY` for https requests. + +The http client that GoToSocial uses will be initialized with the appropriate proxy. + +The environment values may be either a complete URL or a `host[:port]`, in which case the "http" scheme is assumed. The schemes "http", "https", and "socks5" are supported. + +## Application sandboxing + +Although GoToSocial does not currently have any known vulnerabilities, it's +always a good idea to be proactive about security. One way you can help protect +your instance is to run it in a *sandbox* -- an environment that constrains the +actions a program can perform in order to limit the impact of a future exploit. + +[Using Docker](../../installation_guide/docker) to run GoToSocial can work as a +(limited) sandboxing mechanism. For Linux installations, [Linux Security +Modules](https://en.wikipedia.org/wiki/Linux_Security_Modules) such as +[AppArmor](https://www.apparmor.net/) and +[SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) work as a +complementary mechanism that typically provide stronger protections. You should +use + +- **AppArmor** if you're running GoToSocial on Debian, Ubuntu, or OpenSUSE, and +- **SELinux** if you're using CentOS, RHEL, or Rocky Linux. + +For other Linux distributions, you will need to look up what Linux Security +Modules are supported by your kernel. + +!!! note + GoToSocial is currently alpha software, and as more features are implemented + these security policies may quickly become outdated. You may find that using + AppArmor or SELinux causes GoToSocial to fail in unexpected ways until GTS + becomes stable. + +!!! caution + Sandboxing is an _additional_ security mechanism to help defend against + certain kinds of attacks; it _is not_ a replacement for good security + practices. + +### AppArmor + +For Linux distributions supporting AppArmor, there is an AppArmor profile +available in `example/apparmor/gotosocial` that you can use to confine your +GoToSocial instance. If you're using a server (such as a VPS) to deploy +GoToSocial, you can install the AppArmor profile by downloading it and copying +it into the `/etc/apparmor.d/` directory: + +```bash +wget https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/example/apparmor/gotosocial +sudo install -o root -g root gotosocial /etc/apparmor.d/gotosocial +sudo apparmor_parser -Kr /etc/apparmor.d/gotosocial +``` + +If you're using Docker Compose, you should add the following `security_opt` +section to your Compose configuration file: + +```yaml +services: + gotosocial: + ... + security_opt: + - apparmor=gotosocial +``` + +If you're running GoToSocial as a Systemd service, you should instead add this +line under `[Service]`: + +```ini +[Service] +... +AppArmorProfile=gotosocial +``` + +If you're using SQLite, the AppArmor profile expects the database in +`/gotosocial/db/` so you'll need to adjust your configuration paths accordingly. + +For other deployment methods (e.g. a managed Kubernetes cluster), you should +review your platform's documentation for how to deploy an application with an +AppArmor profile. + +#### Disabling the AppArmor profile + +If enabling the AppArmor profile causes your instance to experience issues, you +can uninstall it from the system as follows: + +``` +sudo apparmor_parser -R /etc/apparmor.d/gotosocial +sudo rm -vi /etc/apparmor.d/gotosocial +``` + +You will also want to remove any changes you made to your Compose configuration +or Systemd service file to enable the profile. + +### SELinux + +!!! note + Currently, this SELinux policy only works for the [binary installation + method](../../installation_guide/binary). + +If SELinux is available on your system, you can optionally install [SELinux +policy](https://github.com/lzap/gotosocial-selinux) to further improve security. + +## nginx + +This section contains a number of additional things for configuring nginx. + +### Extra Hardening + +If you want to harden up your NGINX deployment with advanced configuration options, there are many guides online for doing so ([for example](https://beaglesecurity.com/blog/article/nginx-server-security.html)). Try to find one that's up to date. Mozilla also publishes best-practice ssl configuration [here](https://ssl-config.mozilla.org/). + +### Caching Webfinger, Webhost Metadata and Public Key responses + +It's possible to use nginx to cache webfinger, host-meta and public key responses. This may be useful in order to ensure clients still get a response on these endpoints even if your GoToSocial instance is (temporarily) down, or requests are being throttled. + +You'll need to configure two things: + +- A cache path. +- Additional `location` blocks for webfinger and public key requests. + +First, the cache path which needs to happen in the `http` section, usually inside your `nginx.conf` at `/etc/nginx/nginx.conf`: + +```nginx.conf +http { + ... there will be other things here ... + proxy_cache_path /var/cache/nginx keys_zone=gotosocial_ap_public_responses:10m inactive=1w; +} +``` + +This configures a cache of 10MB whose entries will be kept up to one week if they're not accessed. + +The zone is named `gotosocial_ap_public_responses` but you can name it whatever you want. 10MB is a lot of cache keys; you can probably use a smaller value on small instances. + +Second, we need to update our GoToSocial nginx configuration to actually use the cache for the endpoints we want to cache. + +From the below configuration example, copy the entries between `### NEW STUFF STARTS HERE ###` and `### NEW STUFF ENDS HERE ###` and paste them into your GoToSocial nginx configuration. + +```nginx.conf +server { + server_name example.org; + + ### NEW STUFF STARTS HERE ### + + location ~ /.well-known/(webfinger|host-meta)$ { + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_cache gotosocial_ap_public_responses; + proxy_cache_background_update on; + proxy_cache_key $scheme://$host$uri$is_args$query_string; + proxy_cache_valid 200 10m; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429; + proxy_cache_lock on; + add_header X-Cache-Status $upstream_cache_status; + + proxy_pass http://localhost:8080; + } + + location ~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$ { + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_cache gotosocial_ap_public_responses; + proxy_cache_background_update on; + proxy_cache_key $scheme://$host$uri; + proxy_cache_valid 200 604800s; + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429; + proxy_cache_lock on; + add_header X-Cache-Status $upstream_cache_status; + + proxy_pass http://localhost:8080; + } + + ### NEW STUFF ENDS HERE ### + + ### EXISTING STUFF IS BELOW HERE, NOTHING TO CHANGE ### + location / { + proxy_pass http://localhost:8080/; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + # ....... etc +} +``` + +The `proxy_pass` and `proxy_set_header` are mostly the same, but the `proxy_cache*` entries warrant some explanation: + +- `proxy_cache gotosocial_ap_public_responses` tells nginx to use the `gotosocial_ap_public_responses` cache zone we previously created. If you named it something else, you should change this value +- `proxy_cache_background_update on` means nginx will try and refresh a cached resource that's about to expire in the background, to ensure it has a current copy on disk +- `proxy_cache_key` is configured in such a way that it takes the query string into account for caching. So a request for `.well-known/webfinger?acct=user1@example.org` and `.well-known/webfinger?acct=user2@example.org` are not seen as the same. +- `proxy_cache_valid 200 10m;` means we only cache 200 responses from GTS and for 10 minutes. You can add additional lines of these, like `proxy_cache_valid 404 1m;` to cache 404 responses for 1 minute +- `proxy_cache_use_stale` tells nginx it's allowed to use a stale cache entry (so older than 10 minutes) in certain cases +- `proxy_cache_lock on` means that if a resource is not cached and there's multiple concurrent requests for them, the queries will be queued up so that only one request goes through and the rest is then answered from cache +- `add_header X-Cache-Status $upstream_cache_status` will add an `X-Cache-Status` header to the response so you can check if things are getting cached. You can remove this. + +The provided configuration will serve a stale response in case there's an error proxying to GoToSocial, if our connection to GoToSocial times out, if GoToSocial returns a `5xx` status code or if GoToSocial returns 429 (Too Many Requests). The `updating` value says that we're allowed to serve a stale entry if nginx is currently in the process of refreshing its cache. Because we configured `inactive=1w` in the `proxy_cache_path` directive, nginx may serve a response up to one week old if the conditions in `proxy_cache_use_stale` are met. + +### Serving static assets + +By default, GTS will serve assets like the CSS and fonts for the web UI as well as attachments for statuses. However it's very simple to have nginx do this instead and offload GTS from that responsibility. Nginx can generally do a faster job at this too since it's able to use newer functionality in the OS that the Go runtime hasn't necessarily adopted yet. + +There are 2 paths that nginx can handle for us: +* `/assets` which contains fonts, CSS, images etc. for the web UI +* `/fileserver` which serves attachments for status posts when using the local storage backend + +For `/assets` we'll need the value of `web-asset-base-dir` from the configuration, and for `/fileserver` we'll want `storage-local-base-path`. You can then adjust your nginx configuration like this: + +```nginx.conf +server { + server_name example.org; + location /assets/ { + alias web-asset-base-dir/; + autoindex off; + expires 5m; + add_header Cache-Control "public"; + } + + location @fileserver { + proxy_pass http://localhost:8080; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /fileserver/ { + alias storage-local-base-path/; + autoindex off; + expires max; + add_header Cache-Control "private, immutable"; + try_files $uri @fileserver; + } + + location / { + proxy_pass http://localhost:8080/; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + client_max_body_size 40M; + + listen [::]:443 ssl ipv6only=on; # managed by Certbot + listen 443 ssl; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot +} +``` + +The `/fileserver` location is a bit special. When we fail to fetch the media from disk, we want to proxy the request on to GoToSocial so it can try and fetch it. This can be necessary if the media has been removed from disk due to retention settings. The `try_files` directive can't take a `proxy_pass` itself so instead we created the named `@fileserver` location that we pass in last to `try_files`. + +The trailing slashes in the new `location` directives and the `alias` are significant, do not remove those. The `expires` directive adds the necessary headers to inform the client how long it may cache the resource. For assets, which may change on each release, 5 minutes is used in this example. For attachments, which should never change once they're created, `max` is used instead setting the cache expiry to the 31st of December 2037. For other options, see the nginx documentation on the [`expires` directive](https://nginx.org/en/docs/http/ngx_http_headers_module.html#expires). Nginx does not add cache headers to 4xx or 5xx response codes so a failure to fetch an asset won't get cached by clients. The `autoindex off` directive tells nginx to not serve a directory listing. This should be the default but it doesn't hurt to be explicit. The added `add_header` lines set additional options for the `Cache-Control` header: +* `public` is used to indicate that anyone may cache this resource +* `immutable` is used to indicate this resource will never change while it is fresh (it's before the end of the expires) allowing clients to forego conditional requests to revalidate the resource during that timespan diff --git a/docs/getting_started/index.md b/docs/getting_started/index.md new file mode 100644 index 000000000..b9224b62c --- /dev/null +++ b/docs/getting_started/index.md @@ -0,0 +1,75 @@ +# Deployment considerations + +Before deploying GoToSocial, it's important to think through a few things as some choices will have long-term consequences for how you run and manage GoToSocial. + +!!! danger + + It's not supported across the Fediverse to switch between implementations on the same domain. This means that if you run GoToSocial on example.org, you'll run into federation issues if you try to switch to a different implementation like Pleroma/Akkoma, Misskey/Calckey etc. + + In that same vein, if you already have another ActivityPub implementation running on example.org you should not attempt to switch to GoToSocial on that domain. + +## Database + +GoToSocial supports both SQLite and Postgres and you can start using either. We do not currently have tooling to support migrating from SQLite to Postgres or vice-versa, but it is possible in theory. + +SQLite is great for a single-user instance. If you're planning on hosting multiple people it's advisable to use Postgres instead. You can always use Postgres regardless of the instance size. + +!!! tip + Please backup your database. 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. + +## Domain name + +In order to federate with others, you'll need a domain like `example.org`. You can register your domain name through any domain registrar, like [Namecheap](https://www.namecheap.com/). Make sure you pick a registrar that also lets you manage DNS entries, so you can point your domain to the IP of the server that's running your GoToSocial instance. + +You'll commonly see usernames existing at the apex of the domain, for example `@me@example.org` but this is not required. It's perfectly fine to have users exist on `@me@social.example.org` instead. Many people prefer to have usernames on the apex as its shorter to type, but you can use any (subdomain) you control. + +It is possible to have usernames like `@me@example.org` but have GoToSocial running on `social.example.org` instead. This is done by distinguishing between the API domain, called the "host", and the domain used for usernames, called the "account domain". + +!!! danger + It's not possible to safely change whether the host and account domain are different after the fact. It requires regenerating the database and will cause confusion for any server you have already federated with. + +When using a single domain, you only need to configure the "host" in the GoToSocial configuration: + +```yaml +host: "example.org" +``` + +When using a split domain approach, you need to configure both the "host" and the "account-domain": + +```yaml +host: "social.example.org" +account-domain: "example.org" +``` + +## TLS + +For federation to work, you have to use TLS. Most implementations, including GoToSocial, will generally refuse to federate over unencrypted transports. + +GoToSocial comes with built-in support for provisioning certificates through Lets Encrypt. It can also load certificates from disk. If you have a reverse-proxy in front of GoToSocial you can handle TLS at that level instead. + +!!! tip + Make sure you configure the use of modern versions of TLS, TLSv1.2 and higher, in order to keep communications between servers and clients safe. When GoToSocial handles TLS termination this is done automatically for you. If you have a reverse-proxy in use, use the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/). + +## Server / VPS + +GoToSocial aims to fit in small spaces so we try and ensure that the system requirements are fairly minimal: for a single-user instance with about 100 followers/followees, it uses somewhere between 50 to 100MB of RAM. CPU usage is only intensive when handling media (encoding blurhashes, mostly) and/or doing a lot of federation requests at the same time. + +These light requirements mean GtS runs pretty well on something like a Raspberry Pi (a €40 single-board computer). It's been tested on a Raspberry Pi Zero W as well (a €9 computer smaller than a credit card), but it's not quite able to run on that. It should run on a Raspberry Pi Zero W 2 (which costs €14!), but we haven't tested that yet. You can also repurpose an old laptop or desktop to run GoToSocial for you. + +If you decide to use a VPS instead, you can spin yourself up something cheap with Linux running on it. Most of the VPS offerings in the €2-€5 range will perform admirably for a personal GoToSocial instance. + +[Hostwinds](https://www.hostwinds.com/) is a good option here: it's cheap and they throw in a static IP address for free. + +[Greenhost](https://greenhost.net) is also great: it has zero CO2 emissions, but is a bit more costly. + +## Ports + +GoToSocial needs ports `80` and `443` open. + +* `80` is used for Lets Encrypt. As such, you don't need it if you don't use the built-in Lets Encrypt provisioning. +* `443` is used to serve the API on with TLS and is what any instance you're federating with will try to connect to. + +If you can't leave `443` and `80` open on the machine, don't worry! You can configure these ports in GoToSocial, but you'll have to also configure port forwarding to properly forward traffic on `443` and `80` to whatever ports you choose. + +!!! tip + You should configure a firewall on your machine, as well as some protection against brute-force SSH login attempts and the like. A simple frontend to help you configure your firewall is [UFW](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-18-04). You should also consider a tool like [Fail2Ban](https://linuxize.com/post/install-configure-fail2ban-on-ubuntu-20-04/) in order to automatically block malicious users. diff --git a/docs/getting_started/installation/container.md b/docs/getting_started/installation/container.md new file mode 100644 index 000000000..de134542f --- /dev/null +++ b/docs/getting_started/installation/container.md @@ -0,0 +1,123 @@ +# Container + +This guide walks you through getting GoToSocial up and running using the official container images we publish. In this case we'll be using the Docker runtime directly through [Docker Compose](https://docs.docker.com/compose) together with SQLite as the database. + +You can also run GoToSocial using a container orchestration system such as [Kubernetes](https://kubernetes.io/) or [Nomad](https://www.nomadproject.io/), but that is beyond the scope of this guide. + +## Create a Working Directory + +You need a working directory in which your docker-compose file will be located, and a directory for GoToSocial to store data in, so create these directories with the following command: + +```bash +mkdir -p ~/gotosocial/data +``` + +Now change to the working directory you created: + +```bash +cd ~/gotosocial +``` + +## Get the latest docker-compose.yaml + +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: + +```bash +wget https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/example/docker-compose/docker-compose.yaml +``` + +## Edit the docker-compose.yaml + +Because GoToSocial can be configured using [Environment Variables](../../configuration/index.md#environment-variables), we can skip mounting a config.yaml file into the container, to make our configuration simpler. We just need to edit the docker-compose.yaml file to change a few things. + +First open the docker-compose.yaml file in your editor of choice. For example: + +```bash +nano docker-compose.yaml +``` + +### Version + +If desired, update the GoToSocial Docker image tag to the version of GtS you want to use. + +`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, will often be broken. Use with caution. + +You can also replace `latest` with a specific GoToSocial version number. This is recommended when you want to make sure that you don't update your GoToSocial version by accident, which can cause problems. + +The list of releases can be found [right here](https://github.com/superseriousbusiness/gotosocial/releases), with the newest release at the top. Replace `latest` in the docker-compose.yaml with the number of the desired release (without the leading `v` or trailing version name). So for example if you want to run [v0.3.1 Sleepy Sloth](https://github.com/superseriousbusiness/gotosocial/releases/tag/v0.3.1) for whatever reason, you should replace: + +```text +image: superseriousbusiness/gotosocial:latest +``` + +with: + +```text +image: superseriousbusiness/gotosocial:0.3.1 +``` + +### Host + +Change the `GTS_HOST` environment variable to the domain you are running GoToSocial on. + +### User (optional / probably not necessary) + +By default, Dockerized GoToSocial runs with Linux user/group `1000:1000`, which is fine in most cases. If you want to run as a different user/group, you should change the `user` field in the docker-compose.yaml accordingly. + +For example, let's say you created the `~/gotosocial/data` directory for a user with id `1001`, and group id `1001`. If you now try to run GoToSocial without changing the `user` field, it will get a permissions error trying to open its database file in the directory. In this case, you would have to change the `user` field of the docker compose file to `1001:1001`. + +### LetsEncrypt (optional) + +If you want to use [LetsEncrypt](../../configuration/tls.md) for TLS certificates (https), you should also: + +1. Change the value of `GTS_LETSENCRYPT_ENABLED` to `"true"`. +2. Remove the `#` before `- "80:80"` in the `ports` section. +3. (Optional) Set `GTS_LETSENCRYPT_EMAIL_ADDRESS` to a valid email address to receive certificate expiry warnings etc. + +## Start GoToSocial + +With those small changes out of the way, you can now start GoToSocial with the following command: + +```shell +docker-compose up -d +``` + +After running this command, you should get an output like: + +```text +Creating network "gotosocial_gotosocial" with the default driver +Creating gotosocial ... done +``` + +If you want to follow the logs of GoToSocial, you can use: + +```bash +docker logs -f gotosocial +``` + +If everything is OK, you should see something similar to the following: + +```text +time=2022-04-19T09:48:35Z level=info msg=connected to SQLITE database +time=2022-04-19T09:48:35Z level=info msg=MIGRATED DATABASE TO group #1 (20211113114307, 20220214175650, 20220305130328, 20220315160814) func=doMigration +time=2022-04-19T09:48:36Z level=info msg=instance account example.org CREATED with id 01EXX0TJ9PPPXF2C4N2MMMVK50 +time=2022-04-19T09:48:36Z level=info msg=created instance instance example.org with id 01PQT31C7BZJ1Q2Z4BMEV90ZCV +time=2022-04-19T09:48:36Z level=info msg=media manager cron logger: start[] +time=2022-04-19T09:48:36Z level=info msg=media manager cron logger: schedule[now 2022-04-19 09:48:36.096127852 +0000 UTC entry 1 next 2022-04-20 00:00:00 +0000 UTC] +time=2022-04-19T09:48:36Z level=info msg=started media manager remote cache cleanup job: will run next at 2022-04-20 00:00:00 +0000 UTC +time=2022-04-19T09:48:36Z level=info msg=listening on 0.0.0.0:8080 +``` + +## Create your first User + +Now that GoToSocial is running, you should create at least a user for yourself. How to do so is documented in our [Creating users](../user_creation.md) guide. + +### Done + +GoToSocial should now be running on your machine! To verify this, open your browser and go to `http://localhost:443`. You should see the GoToSocial landing page. Well done! + +## (Optional) Reverse Proxy + +If you want to run other webservers on port 443 or want to add an additional layer of security you might want to use a [reverse proxy](../reverse_proxy/index.md). We have guides available for a couple of popular open source options and will gladly take pull requests to add more. diff --git a/docs/getting_started/installation/index.md b/docs/getting_started/installation/index.md new file mode 100644 index 000000000..3457a69c6 --- /dev/null +++ b/docs/getting_started/installation/index.md @@ -0,0 +1,14 @@ +# Installation + +As we noted in [Releases](../releases.md), we publish official binary release as well as containers. We have a number of guides available on how to deploy your own GoToSocial instance this way. + +Before proceeding with your installation, please ensure you've read through the [Deployment considerations](../index.md) first and have a domain and server ready to go. + +Also take a minute to familiarise yourself with [how to configure](../../configuration/index.md) GoToSocial. + +## Guides + +For third-party releases we don't provide guides on how to use them. You need to refer to their own documentation instead. Our guides might still be useful to review in order to familiarise yourself with which configuration options you likely want to set and tweak. + +* [Bare metal](metal.md) +* [Container](container.md) diff --git a/docs/getting_started/installation/metal.md b/docs/getting_started/installation/metal.md new file mode 100644 index 000000000..3040dbbb8 --- /dev/null +++ b/docs/getting_started/installation/metal.md @@ -0,0 +1,123 @@ +# Bare metal + +This guide walks you through getting GoToSocial up and running on bare metal using the official binary releases. + +## Prepare VPS + +In a terminal on the VPS or your homeserver, make the directory that GoToSocial will run from, the directory it will use as storage, and the directory it will store LetsEncrypt certificates in: + +```bash +mkdir /gotosocial && mkdir /gotosocial/storage && mkdir /gotosocial/storage/certs +``` + +If you don't have root permissions on the machine, use something like `~/gotosocial` instead. + +## Download Release + +In a terminal on the VPS or your homeserver, cd into the base directory for GoToSocial you just created above: + +```bash +cd /gotosocial +``` + +Now, download the latest GoToSocial release archive corresponding to the operating system and architecture you're running on. + +(You can find the list of releases [right here](https://github.com/superseriousbusiness/gotosocial/releases), arranged with the newest release at the top.) + +For example, to download version 0.5.2 for running on 64-bit Linux: + +```bash +wget https://github.com/superseriousbusiness/gotosocial/releases/download/v0.5.2/gotosocial_0.5.2_linux_amd64.tar.gz +``` + +Then extract it: + +```bash +tar -xzf gotosocial_0.5.2_linux_amd64.tar.gz +``` + +This will put the `gotosocial` binary in your current directory, in addition to the `web` folder, which contains assets for the web frontend, and an `example` folder, which contains a sample configuration file. + +## Edit Configuration File + +Copy the configuration file from the example folder into your current directory: + +```bash +cp ./example/config.yaml . +``` + +Now open the file in your text editor of choice so that you can set some important configuration values. 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`). + +The above options assume you're using SQLite as your database. If you want to use Postgres instead, see [here](../../configuration/database.md) for the config options. + +## Run the Binary + +You can now run the binary. + +Start the GoToSocial server with the following command: + +```bash +./gotosocial --config-path ./config.yaml server start +``` + +The server should now start up and you should be able to access the splash page by navigating to your domain in the browser. Note that it might take up to a minute or so for your LetsEncrypt certificates to be created for the first time, so refresh a few times if necessary. + +Note that for this example we're assuming that we're allowed to run on port 443 (standard https port), and that nothing else is running on this port. + +## Create your user + +You can use the GoToSocial binary to also create and promote your user account. This is all documented in our [Creating users](../user_creation.md) guide. + +## Login + +You should now be able to log in to your instance using the email address and password of the account you just created. We recommend using [Semaphore](https://semaphore.social) or [Tusky](https://tusky.app) for this. + +## (Optional) Enable the systemd service + +If you don't like manually starting GoToSocial on every boot you might want to create a systemd service that does that for you. + +First stop your GoToSocial instance. + +Then create a new user and group for your GoToSocial installation: + +```bash +sudo useradd -r gotosocial +sudo groupadd gotosocial +sudo usermod -a -G gotosocial gotosocial +``` + +Then make them the owner of your GoToSocial installation since they will need to read and write in it: + +```bash +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. + +Copy it to `/etc/systemd/system/gotosocial.service`: + +```bash +sudo cp /gotosocial/example/gotosocial.service /etc/systemd/system/ +``` + +Then use `sudoedit /etc/systemd/system/gotosocial.service` to change the `ExecStart=` and `WorkingDirectory=` lines according to your installation. + +If you have been following this guide word for word the defaults should be fine. + +After you're done enable the service: + +```bash +sudo systemctl enable --now gotosocial.service +``` + +## (Optional) Reverse proxy + +If you want to run other webservers on port 443 or want to add an additional layer of security you might want to use a [reverse proxy](../reverse_proxy/index.md). We have guides available for a couple of popular open source options and will gladly take pull requests to add more. diff --git a/docs/getting_started/releases.md b/docs/getting_started/releases.md new file mode 100644 index 000000000..14b6e4a58 --- /dev/null +++ b/docs/getting_started/releases.md @@ -0,0 +1,40 @@ +# Releases + +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. + +## Binary releases +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. + +## 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!). + +[](https://repology.org/project/gotosocial/versions) + +### Deployment tools + +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). diff --git a/docs/getting_started/reverse_proxy/apache-httpd.md b/docs/getting_started/reverse_proxy/apache-httpd.md new file mode 100644 index 000000000..9522a0001 --- /dev/null +++ b/docs/getting_started/reverse_proxy/apache-httpd.md @@ -0,0 +1,250 @@ +# Apache HTTP Server + +## Requirements + +For this you will need the Apache HTTP Server. + +That is a fairly popular package so your distro will probably have it. + +### Ubuntu + +```bash +sudo apt install apache2 +``` + +### Arch + +```bash +sudo pacman -S apache +``` + +### OpenSuse + +```bash +sudo zypper install apache2 +``` + +### Install modules + +You'll also need to install additional modules for Apache HTTP Server. You can do that with the following command: + +```bash +sudo a2enmod proxy_http md ssl headers rewrite +``` + +## Configure GoToSocial + +We're going to have Apache handle LetsEncrypt certificates, so you need to turn off built-in LetsEncrypt support in your GoToSocial config. + +First open the file in your text editor: + +```bash +sudoedit /gotosocial/config.yaml +``` + +Then set `letsencrypt-enabled: false`. + +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. + +If GoToSocial is already running, restart it. + +```bash +sudo systemctl restart gotosocial.service +``` + +Or if you don't have a systemd service just restart it manually. + +## Set up Apache HTTP Server with SSL managed using MD module + +Now we'll configure Apache HTTP Server to serve GoToSocial requests. + +First we'll write a configuration for Apache HTTP Server and put it in `/etc/apache2/sites-available`: + +```bash +sudo mkdir -p /etc/apache2/sites-available/ +sudoedit /etc/apache2/sites-available/example.com.conf +``` + +In the above `sudoedit` command, replace `example.com` with the hostname of your GoToSocial server. + +The file you're about to create should look a bit like this: + +```apache +MDomain example.com auto +MDCertificateAgreement accepted + +<VirtualHost *:80 > + ServerName example.com +</VirtualHost> + +<VirtualHost *:443> + ServerName example.com + + RewriteEngine On + RewriteCond %{HTTP:Upgrade} websocket [NC] + RewriteCond %{HTTP:Connection} upgrade [NC] + # set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758 + RewriteRule ^/?(.*) "ws://127.0.0.1:8080/$1" [P,L] + + SSLEngine On + ProxyPreserveHost On + # set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758 + ProxyPass / http://127.0.0.1:8080/ + ProxyPassReverse / http://127.0.0.1:8080/ + + RequestHeader set "X-Forwarded-Proto" expr=https +</VirtualHost> +``` + +or, if you have [Apache httpd 2.4.47+](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#protoupgrade), you can get rid of both `mod_rewrite` and `mod_proxy_wstunnel` and simplify the whole config to: + +```apache +MDomain example.com auto +MDCertificateAgreement accepted + +<VirtualHost *:80 > + ServerName example.com +</VirtualHost> + +<VirtualHost *:443> + ServerName example.com + + SSLEngine On + ProxyPreserveHost On + # set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758 + ProxyPass / http://127.0.0.1:8080/ upgrade=websocket + ProxyPassReverse / http://127.0.0.1:8080/ + + RequestHeader set "X-Forwarded-Proto" expr=https +</VirtualHost> +``` + +Again, replace occurrences of `example.com` in the above config file with the hostname of your GtS server. If your domain name is `gotosocial.example.com`, then `gotosocial.example.com` would be the correct value. + +You should also change `http://127.0.0.1:8080` to the correct address and port (if it's not on `127.0.0.1:8080`) of your GtS server. For example, if you're running GoToSocial on another machine with the local ip of `192.168.178.69` and on port `8080` then `http://192.168.178.69:8080/` would be the correct value. + +`Rewrite*` directives are needed to ensure that Websocket streaming connections also work. See the [websocket](./websocket.md) document for more information on this. + +`ProxyPreserveHost On` is essential: It guarantees that the proxy and the GoToSocial speak of the same Server name. If not, GoToSocial will build the wrong authentication headers, and all attempts at federation will be rejected with 401 Unauthorized. + +By default, apache sets `X-Forwarded-For` in forwarded requests. To make this and rate limiting work, set the `trusted-proxies` configuration variable. See the [rate limiting](../../api/ratelimiting.md) and [general configuration](../../configuration/general.md) docs + +Save and close the config file. + +Now we'll need to link the file we just created to the folder that Apache HTTP Server reads configurations for active sites from. + +```bash +sudo mkdir /etc/apache2/sites-enabled +sudo ln -s /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-enabled/ +``` + +In the above `ln` command, replace `example.com` with the hostname of your GoToSocial server. + +Now check for configuration errors. + +```bash +sudo apachectl -t +``` + +If everything is fine you should get this as output: + +```text +Syntax OK +``` + +Everything working? Great! Then restart Apache HTTP Server to load your new config file. + +```bash +sudo systemctl restart apache2 +``` + +Now, monitor the logs to see when the new LetsEncrypt certificate arrives (`tail -F /var/log/apache2/error.log`), and then reload Apache one last time with the above `systemctl restart` command. After that you should be good to go! + +Apache HTTP Server needs to be restart (or reloaded), every time `mod_md` gets a new certificate; see the module's docs for [more information](https://github.com/icing/mod_md#how-to-manage-server-reloads). + +Depending on your version of Apache HTTP Server, you may see the following error: `error (specific information not available): acme problem urn:ietf:params:acme:error:invalidEmail: Error creating new account :: contact email "webmaster@localhost" has invalid domain : Domain name needs at least one dot` + +If this happens, you'll need to do one (or all) of the below: + +1. Update `/etc/apache2/sites-enabled/000-default.conf` and change the `ServerAdmin` value to a valid email address (then reload Apache HTTP Server). +2. Add the line `MDContactEmail your.email.address@whatever.com` below the `MDomain` line in `/etc/apache2/sites-available/example.com.conf`, replacing `your.email.address@whatever.com` with a valid email address, and `example.com` with your GtS host name. + +## Set up Apache HTTP Server with SSL managed manually or by an external software (e.g. Certbot or acme.sh) + +If you prefer to have a manual setup or setting SSL using a different service to manage it (Certbot, etc), then you can use a simpler setup for your Apache HTTP Server. + +First we'll write a configuration for Apache HTTP Server and put it in `/etc/apache2/sites-available`: + +```bash +sudo mkdir -p /etc/apache2/sites-available/ +sudoedit /etc/apache2/sites-available/example.com.conf +``` + +In the above `sudoedit` command, replace `example.com` with the hostname of your GoToSocial server. + +The file you're about to create should look initially for both 80 (required) and 443 ports (optional) a bit like this: + +```apache +<VirtualHost *:80> + ServerName example.com + + RewriteEngine On + RewriteCond %{HTTP:Upgrade} websocket [NC] + RewriteCond %{HTTP:Connection} upgrade [NC] + # set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758 + RewriteRule ^/?(.*) "ws://127.0.0.1:8080/$1" [P,L] + + ProxyPreserveHost On + # set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758 + ProxyPass / http://127.0.0.1:8080/ + ProxyPassReverse / http://127.0.0.1:8080/ + +</VirtualHost> +``` + +Again, replace occurrences of `example.com` in the above config file with the hostname of your GtS server. If your domain name is `gotosocial.example.com`, then `gotosocial.example.com` would be the correct value. + +You should also change `http://127.0.0.1:8080` to the correct address and port (if it's not on `127.0.0.1:8080`) of your GtS server. For example, if you're running GoToSocial on another machine with the local ip of `192.168.178.69` and on port `8080` then `http://192.168.178.69:8080/` would be the correct value. + +`Rewrite*` directives are needed to ensure that Websocket streaming connections also work. See the [websocket](websocket.md) document for more information on this. + +`ProxyPreserveHost On` is essential: It guarantees that the proxy and the GoToSocial speak of the same Server name. If not, GoToSocial will build the wrong authentication headers, and all attempts at federation will be rejected with 401 Unauthorized. + +In the case of providing an initial setup for the 443 port looking for additional managing by an external tool, you could use default certificates provided by the server which you can find referenced in the `default-ssl.conf` file at `/etc/apache2/sites-available/`. + +Save and close the config file. + +Now we'll need to link the file we just created to the folder that Apache HTTP Server reads configurations for active sites from. + +```bash +sudo mkdir /etc/apache2/sites-enabled +sudo ln -s /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-enabled/ +``` + +In the above `ln` command, replace `example.com` with the hostname of your GoToSocial server. + +Now check for configuration errors. + +```bash +sudo apachectl -t +``` + +If everything is fine you should get this as output: + +```text +Syntax OK +``` + +Everything working? Great! Then restart Apache HTTP Server to load your new config file. + +```bash +sudo systemctl restart apache2 +``` + +## Troubleshooting + +If you cannot connect to the site in your browser, the reverse proxy setup doesn't work. Compare the Apache log file (`tail -F /var/log/apache2/access.log`) with the GoToSocial log file. Requests made must show up in both places. Double check the `ProxyPass` setting. + +If you can connect but your posts don't federate and your account cannot be found from elsewhere, check your logs. Federation is broken if you see messages attempting to read your profile (something like `level=INFO … method=GET statusCode=401 path=/users/your_username msg="Unauthorized: …"`) or post to your inbox (something like `level=INFO … method=POST statusCode=404 path=/your_username/inbox msg="Not Found: …"`). Double check the `ProxyPreserveHost` setting. + +If you can connect but you cannot authorize your account in a Mastodon client app, check your headers. Use `curl -I https://example.com` and look for the `Content-Security-Policy` header. If your webserver sets it, you might have to unset it. One way to do that is to use `Header unset Content-Security-Policy` in the Apache site config file (something like `example.com.conf`). diff --git a/docs/getting_started/reverse_proxy/caddy.md b/docs/getting_started/reverse_proxy/caddy.md new file mode 100644 index 000000000..9af8d5e26 --- /dev/null +++ b/docs/getting_started/reverse_proxy/caddy.md @@ -0,0 +1,108 @@ +# Caddy 2 + +## Requirements + +For this guide you will need [Caddy 2](https://caddyserver.com/), there are no other dependencies. Caddy manages Lets Encrypt certificates and renewal for them. + +Caddy is in the most popular package managers, or you can get a static binary. For all latest installation guides, refer to [their manual](https://caddyserver.com/docs/install). + +### Debian, Ubuntu, Raspbian + +```bash +# Add the keyring for their custom repository. +sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https +curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg +curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list + +# Update packages and install it +sudo apt update +sudo apt install caddy +``` + +### Fedora, Redhat, Centos + +```bash +dnf install 'dnf-command(copr)' +dnf copr enable @caddy/caddy +dnf install caddy +``` + +### Arch + +```bash +pacman -Syu caddy +``` + +### FreeBSD +```bash +sudo pkg install caddy +``` + +## Configure GoToSocial + +If GoToSocial is already running, stop it. + +```bash +sudo systemctl stop gotosocial +``` +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 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. + +## Set up Caddy + +We will configure Caddy 2 to use GoToSocial on our main domain example.org. Since Caddy takes care of obtaining the Lets Encrypt certificate, we only need to configure it properly once. + +In most simple use cases Caddy defaults to a file called Caddyfile. It can reload on changes, or can be configured through an HTTP API for zero downtime, but this is out of our current scope. + +```bash +sudo mkdir -p /etc/caddy +sudo vim /etc/caddy/Caddyfile +``` + +While editing the file above, you should replace 'example.org' with your domain. Your domain should occur twice in the current configuration. If you have chosen another port number for GoToSocial other than port 8080, change the port number on the reverse proxy line to match that. + +The file you're about to create should look like this: + +```Caddyfile +example.org { + # Optional, but recommended, compress the traffic using proper protocols + encode zstd gzip + + # 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_interval -1 + } +} +``` + +By default, caddy sets `X-Forwarded-For` in forwarded requests. To make this and rate limiting work, set the `trusted-proxies` configuration variable. See the [rate limiting](../../api/ratelimiting.md) and [general configuration](../../configuration/general.md) docs + +For advanced configuration check the [reverse_proxy directive](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy) at the Caddy documentation. + +Now check for configuration errors. + +```bash +sudo caddy validate +``` + +If everything is fine, you should get some info lines as output. Unless there are lines marked with *[err]* in front of them, you are all set. + +Everything working? Great! Then restart caddy to load your new config file. + +```bash +sudo systemctl restart caddy +``` + +If everything went right, you're now all set to enjoy your GoToSocial instance, so we are going to start it again. + +```bash +sudo systemctl start gotosocial +``` + +## Results + +You should now be able to open the splash page for your instance in your web browser, and will see that it runs under HTTPS! diff --git a/docs/getting_started/reverse_proxy/index.md b/docs/getting_started/reverse_proxy/index.md new file mode 100644 index 000000000..927968df0 --- /dev/null +++ b/docs/getting_started/reverse_proxy/index.md @@ -0,0 +1,43 @@ +# Reverse proxy + +GoToSocial can be exposed directly to the internet. However, many folks prefer to have a reverse proxy handle connections from the outside instead. This can also give greater control over TLS configurations and enables some more advanced scenario's like asset caching. + +## General procedure + +In order to use a reverse-proxy, you'll typically want to do a few things: + +* Configure some way to get TLS certificates for the host domain +* Bind GoToSocial to a local IP instead of a public IP and a non-priviledged port. Adjust the `bind-address` and `port` configuration options +* Disable Lets Encrypt in GoToSocial if you were using it. Set `letsencrypt-enabled` to `false` +* Configure the reverse proxy to handle TLS and proxy requests to GoToSocial + +!!! warning + Do not change the value of the `host` configuration option. This needs to remain the actual domain name the instance is running on as seen by other instances on the internet. Instead, change the `bind-address` and update the `port` and `trusted-proxies`. + +### Container + +When you deploy GoToSocial using our [example Docker Compose guide](../installation/container.md), it will bind to port `443` by default as it assumes you want to directly expose it to the internet. In order to run it behind a reverse proxy, you need to change that. + +In the compose file: + +* Comment out the `- "443:8080"` line in the `ports` definition +* If you had enabled Lets Encrypt support: + * Comment out the `- "80:80"` line in the `ports` definition + * Set `GTS_LETSENCRYPT_ENABLED` back to `"false"` or comment it out +* Uncomment the `- "127.0.0.1:8080:8080"` line instead + +This now causes Docker to only forward connections on `127.0.0.1` on port `8080` to the container, effectively isolating it from the outside world. You can now tell your reverse-proxy to send requests there instead. + +## Guides + +We have guides available for the following servers: + +* [nginx](nginx.md) +* [Apache httpd](apache-httpd.md) +* [Caddy 2](caddy.md) + +## WebSockets + +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. diff --git a/docs/getting_started/reverse_proxy/nginx.md b/docs/getting_started/reverse_proxy/nginx.md new file mode 100644 index 000000000..377f2ef02 --- /dev/null +++ b/docs/getting_started/reverse_proxy/nginx.md @@ -0,0 +1,186 @@ +# NGINX + +## Requirements + +For this you will need [Certbot](https://certbot.eff.org/), the Certbot NGINX plugin and of course [NGINX](https://www.nginx.com/) itself. + +These are popular packages so your distro will probably have them. + +### Ubuntu + +```bash +sudo apt install certbot python3-certbot-nginx nginx +``` + +### Arch + +```bash +sudo pacman -S certbot certbot-nginx nginx +``` + +### OpenSuse + +```bash +sudo zypper install nginx python3-certbot python3-certbot-nginx +``` + +## Configure GoToSocial + +If GoToSocial is already running, stop it. + +```bash +sudo systemctl stop gotosocial +``` + +Or if you don't have a systemd service just stop it manually. + +In your GoToSocial config turn off letsencrypt by setting `letsencrypt-enabled` to `false`. + +If you we 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. + +## Set up NGINX + +First we will set up NGINX to serve GoToSocial as unsecured http and then use Certbot to automatically upgrade it to serve https. + +Please do not try to use it until that's done or you'll risk transmitting passwords over clear text, or breaking federation. + +First we'll write a configuration for NGINX and put it in `/etc/nginx/sites-available`. + +```bash +sudo mkdir -p /etc/nginx/sites-available +sudoedit /etc/nginx/sites-available/yourgotosocial.url.conf +``` + +In the above commands, replace `yourgotosocial.url` with your actual GoToSocial host value. So if your `host` is set to `example.org`, then the file should be called `/etc/nginx/sites-available/example.org.conf` + +The file you're about to create should look like this: + +```nginx.conf +server { + listen 80; + listen [::]:80; + server_name example.org; + location / { + # set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758 + proxy_pass http://127.0.0.1:8080; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + client_max_body_size 40M; +} +``` + +Change `proxy_pass` to the ip and port that you're actually serving GoToSocial on (if it's not on `127.0.0.1:8080`), and change `server_name` to your own domain name. + +If your domain name is `example.org` then `server_name example.org;` would be the correct value. + +If you're running GoToSocial on another machine with the local ip of 192.168.178.69 and on port 8080 then `proxy_pass http://192.168.178.69:8080;` would be the correct value. + +**Note**: You can remove the line `listen [::]:80;` if your server is not ipv6 capable. + +**Note**: `proxy_set_header Host $host;` is essential. It guarantees that the proxy and GoToSocial use the same server name. If not, GoToSocial will build the wrong authentication headers, and all attempts at federation will be rejected with 401. + +**Note**: The `Connection` and `Upgrade` headers are used for WebSocket connections. See the [WebSocket docs](websocket.md). + +**Note**: `client_max_body_size` is set to 40M in this example, which is the default max video upload size for GoToSocial. You can make this value larger or smaller if necessary. The nginx default is only 1M, which is rather too small. + +**Note**: To make `X-Forwarded-For` and rate limiting work, set the `trusted-proxies` configuration variable. See the [rate limiting](../../api/ratelimiting.md) and [general configuration](../../configuration/general.md) docs + +Next we'll need to link the file we just created to the folder that nginx reads configurations for active sites from. + +```bash +sudo mkdir -p /etc/nginx/sites-enabled +sudo ln -s /etc/nginx/sites-available/yourgotosocial.url.conf /etc/nginx/sites-enabled/ +``` + +Again, replace `yourgotosocial.url` with your actual GoToSocial host value. + +Now check for configuration errors. + +```bash +sudo nginx -t +``` + +If everything is fine you should get this as output: + +```text +nginx: the configuration file /etc/nginx/nginx.conf syntax is ok +nginx: configuration file /etc/nginx/nginx.conf test is successful +``` + +Everything working? Great! Then restart nginx to load your new config file. + +```bash +sudo systemctl restart nginx +``` + +## Setting up SSL with certbot + +You should now be able to run certbot and it will guide you through the steps required to enable https for your instance. + +```bash +sudo certbot --nginx +``` + +After you do, it should have automatically edited your configuration file to enable https. + +Reload NGINX one last time: + +```bash +sudo systemctl restart nginx +``` + +Now start GoToSocial again: + +```bash +sudo systemctl start gotosocial +``` + +## Results + +You should now be able to open the splash page for your instance in your web browser, and will see that it runs under https! + +If you open the NGINX config again, you'll see that Certbot added some extra lines to it. + +**Note**: This may look a bit different depending on the options you chose while setting up Certbot, and the NGINX version you're using. + +```nginx.conf +server { + server_name example.org; + location / { + # set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758 + proxy_pass http://127.0.0.1:8080; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + } + client_max_body_size 40M; + + listen [::]:443 ssl ipv6only=on; # managed by Certbot + listen 443 ssl; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot +} + +server { + if ($host = example.org) { + return 301 https://$host$request_uri; + } # managed by Certbot + + listen 80; + listen [::]:80; + server_name example.org; + return 404; # managed by Certbot +} +``` + +A number of additional configurations for nginx, including static asset serving and caching, are documented in the [Advanced](../advanced.md) section of our documentation. diff --git a/docs/getting_started/reverse_proxy/websocket.md b/docs/getting_started/reverse_proxy/websocket.md new file mode 100644 index 000000000..ec7c107a9 --- /dev/null +++ b/docs/getting_started/reverse_proxy/websocket.md @@ -0,0 +1,43 @@ +# WebSocket + +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. + +In order to use this functionality, you need to ensure that whatever proxy you've configured GoToSocial to run behind allows WebSocket connections through. + +The WebSocket endpoint is located at `wss://example.org/api/v1/streaming` where `example.org` is the hostname of your GoToSocial instance. + +The WebSocket endpoint uses the same port as configured in the `port` section of your [general config](../../configuration/general.md). + +Typical WebSocket **request** headers as sent by Pinafore look like the following: + +```text +Host: example.org +User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0 +Accept: */* +Accept-Language: en-US,en;q=0.5 +Accept-Encoding: gzip, deflate, br +Sec-WebSocket-Version: 13 +Origin: https://pinafore.social +Sec-WebSocket-Protocol: null +Sec-WebSocket-Extensions: permessage-deflate +Sec-WebSocket-Key: YWFhYWFhYm9vYmllcwo= +DNT: 1 +Connection: keep-alive, Upgrade +Sec-Fetch-Dest: websocket +Sec-Fetch-Mode: websocket +Sec-Fetch-Site: cross-site +Pragma: no-cache +Cache-Control: no-cache +Upgrade: websocket +``` + +Typical WebSocket **response** headers as returned by GoToSocial look like the following: + +```text +HTTP/1.1 101 Switching Protocols +Upgrade: websocket +Connection: Upgrade +Sec-WebSocket-Accept: WVdGaFlXRmhZbTl2WW1sbGN3bz0K +``` + +Whatever your setup, you need to ensure that these headers are allowed through your proxy, which may require extra configuration depending on the exact proxy being used. diff --git a/docs/getting_started/tracing.md b/docs/getting_started/tracing.md new file mode 100644 index 000000000..34b47f563 --- /dev/null +++ b/docs/getting_started/tracing.md @@ -0,0 +1,44 @@ +# Tracing + +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]. + +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. + +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: + +```yaml +tracing-enabled: true +tracing-transport: "grpc" +tracing-endpoint: "localhost:4317" +tracing-insecure: true +``` + +[otel]: https://opentelemetry.io/ +[obs]: ../configuration/observability.md +[tempo]: https://grafana.com/oss/tempo/ +[grafana]: https://grafana.com/oss/grafana/ +[ext]: https://github.com/superseriousbusiness/gotosocial/tree/main/example/tracing + +## Querying and visualising traces + +Once you execute a few queries against your instance, you'll be able to find them in Grafana. You can use the Explore tab and pick Tempo as the datasource. Because our example configuration for Grafana enables [TraceQL][traceql], the Explore tab will have the TraceQL query type selected by default. You can switch to "Search" instead and find all traces emitted by GoToSocial under the "GoToSocial" service name. + +Using TraceQL, a simple query to find all traces related to requests to `/api/v1/instance` would look like this: + +``` +{.http.route = "/api/v1/instance"} +``` + +If you wanted to see all GoToSocial traces, you could instead run: + +``` +{.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. + + + +[traceql]: https://grafana.com/docs/tempo/latest/traceql/ diff --git a/docs/getting_started/user_creation.md b/docs/getting_started/user_creation.md new file mode 100644 index 000000000..806abf0fb --- /dev/null +++ b/docs/getting_started/user_creation.md @@ -0,0 +1,50 @@ +# Creating users + +Regardless of the installation method, you'll need to create some users. GoToSocial currently doesn't have a way for users to be created through the web UI, or for people to sign-up through the web UI. + +Using the CLI, you can create a user: + +```sh +$ gotosocial --config-path /path/to/config.yaml \ + admin account create \ + --username some_username \ + --email some_email@whatever.org \ + --password 'SOME_PASSWORD' +``` + +In the above command, replace `some_username` with your desired username, `some_email@whatever.org` with the email address you want to associate with your account, and `SOME_PASSWORD` with a secure password. + +If you want your user to have admin rights, you can promote them using a similar command: + +```sh +$ gotosocial --config-path /path/to/config.yaml \ + admin account promote --username some_username +``` + +Replace `some_username` with the username of the account you just created. + +!!! info + When running these commands, you'll get a bit of output like the following: + + ```text + time=XXXX level=info msg=connected to SQLITE database + time=XXXX level=info msg=there are no new migrations to run func=doMigration + time=XXXX level=info msg=closing db connection + ``` + + This is normal and indicates that the commands ran as expected. + +## Containers + +When running GoToSocial from a container, you'll need to execute the above command in the conatiner instead. How to do this varies based on your container runtime, but for Docker it should look like: + +```sh +$ docker exec -it CONTAINER_NAME_OR_ID \ + /gotosocial/gotosocial \ + admin account create \ + --username some_username \ + --email someone@example.org \ + --password 'some_very_good_password' +``` + +If you followed our Docker guide, the container name will be `gotosocial`. Both the name and the ID can be retrieved through `docker ps`. |