Set up GoToSocial with separate domains

← All guides

Want your address to be @name@example.com while GoToSocial runs on social.example.com? That works, and your website stays on the main domain. This guide shows you what to set.

What the two values mean

ValueExamplePurpose
account-domainexample.comAppears in addresses: @name@example.com
hostsocial.example.comWhere GoToSocial runs and where apps log in

Other servers ask example.com first. The web server on your main domain redirects these requests to social.example.com.

Important: Set both values before the very first start. Once your instance has talked to other servers, this can no longer be changed. You would have to rebuild the database, and the admins of every connected instance would have to adjust their data.

Step 1: DNS

Create the subdomain at your DNS provider:

NameTypeValue
socialAIPv4 address of the GoToSocial server
socialAAAAIPv6 address of the GoToSocial server, if it has one

The records for your main domain stay as they are. It only needs a valid HTTPS certificate. See Connect your own domain for more.

Step 2: GoToSocial

Add both values to config.yaml:

host: "social.example.com"
account-domain: "example.com"

With Docker, you can use environment variables instead:

GTS_HOST=social.example.com
GTS_ACCOUNT_DOMAIN=example.com

Step 3: Redirect on the main domain

These settings go on the server that hosts example.com. Replace social.example.com with your own address.

nginx

In the server block for port 443:

location ~ ^/\.well-known/(webfinger|host-meta|nodeinfo)$ {
    add_header Access-Control-Allow-Origin "*" always;
    return 301 https://social.example.com$request_uri;
}

Then check and reload: nginx -t && systemctl reload nginx

Apache 2

In the VirtualHost for port 443. The header line needs mod_headers (a2enmod headers):

<LocationMatch "^/\.well-known/(webfinger|host-meta|nodeinfo)$">
    Header always set Access-Control-Allow-Origin "*"
</LocationMatch>
Redirect 301 /.well-known/webfinger https://social.example.com/.well-known/webfinger
Redirect 301 /.well-known/host-meta https://social.example.com/.well-known/host-meta
Redirect 301 /.well-known/nodeinfo https://social.example.com/.well-known/nodeinfo

Then check and reload: apachectl configtest && systemctl reload apache2

Apache 2 with .htaccess, for example with WordPress

The rule has to come before the # BEGIN WordPress block:

RewriteEngine On
RewriteRule ^\.well-known/(webfinger|host-meta|nodeinfo)$ https://social.example.com/.well-known/$1 [R=301,L]

Only redirect these three paths: Do not redirect /api/. It confuses some apps during login.

Step 4: Test

curl -sI -A 'gotosocial' \
  'https://example.com/.well-known/webfinger?resource=acct:name@example.com'

The response should look like this. The ?resource=… part has to survive:

HTTP/2 301
location: https://social.example.com/.well-known/webfinger?resource=acct:name@example.com

If GoToSocial is already running, follow the redirect. You will get JSON with acct:name@example.com:

curl -sL -A 'gotosocial' \
  'https://example.com/.well-known/webfinger?resource=acct:name@example.com'

Finally, search for @name@example.com from another instance.

If it does not work

  • It works in the browser but not in the test: A bot block, firewall or CDN is blocking server requests, often with 403 or 418. Exclude the three paths.
  • nginx returns the block despite the redirect: An if with return directly in the server block runs before any location block.
  • nginx returns 404: A location ^~ /.well-known/ block takes priority. Narrow it, for example to /.well-known/acme-challenge/.
  • The account cannot be found: Check that ?resource=… survives.
  • Apps cannot log in: Enter social.example.com in the app, not the main domain.

Want me to take care of this?

I run GoToSocial with custom domains on servers in Germany and set this up for you.