diff --git a/cmd/gotosocial/main.go b/cmd/gotosocial/main.go
index fde83e623..e8bc793bd 100644
--- a/cmd/gotosocial/main.go
+++ b/cmd/gotosocial/main.go
@@ -69,10 +69,16 @@ func main() {
 			},
 			&cli.StringFlag{
 				Name:    flagNames.Host,
-				Usage:   "Hostname to use for the server (eg., example.org, gotosocial.whatever.com)",
+				Usage:   "Hostname to use for the server (eg., example.org, gotosocial.whatever.com). DO NOT change this on a server that's already run!",
 				Value:   defaults.Host,
 				EnvVars: []string{envNames.Host},
 			},
+			&cli.StringFlag{
+				Name:    flagNames.AccountDomain,
+				Usage:   "Domain to use in account names (eg., example.org, whatever.com). If not set, will default to the setting for host. DO NOT change this on a server that's already run!",
+				Value:   defaults.AccountDomain,
+				EnvVars: []string{envNames.AccountDomain},
+			},
 			&cli.StringFlag{
 				Name:    flagNames.Protocol,
 				Usage:   "Protocol to use for the REST api of the server (only use http for debugging and tests!)",
diff --git a/example/config.yaml b/example/config.yaml
index b26322812..149da46dd 100644
--- a/example/config.yaml
+++ b/example/config.yaml
@@ -27,12 +27,25 @@ logLevel: "info"
 # Default: "gotosocial"
 applicationName: "gotosocial"
 
-# String. Hostname/domain to use for the server. Defaults to localhost for local testing,
+# 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.
-# Examples: ["example.org","some.server.com"]
+# 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.
+# 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!
+# Examples: ["example.org","server.com"]
+# Default: ""
+accountDomain: ""
+
 # String. Protocol to use for the server. Only change to http for local testing!
 # Options: ["http","https"]
 # Default: "https"
diff --git a/internal/api/s2s/webfinger/webfingerget.go b/internal/api/s2s/webfinger/webfingerget.go
index 416a75f3b..1d723e67c 100644
--- a/internal/api/s2s/webfinger/webfingerget.go
+++ b/internal/api/s2s/webfinger/webfingerget.go
@@ -50,23 +50,23 @@ func (m *Module) WebfingerGETRequest(c *gin.Context) {
 		return
 	}
 
-	usernameDomain := strings.Split(withAcct[1], "@")
-	if len(usernameDomain) != 2 {
+	usernameAndAccountDomain := strings.Split(withAcct[1], "@")
+	if len(usernameAndAccountDomain) != 2 {
 		l.Debugf("aborting request because username and domain could not be parsed from %s", withAcct[1])
 		c.JSON(http.StatusBadRequest, gin.H{"error": "bad request"})
 		return
 	}
-	username := strings.ToLower(usernameDomain[0])
-	domain := strings.ToLower(usernameDomain[1])
-	if username == "" || domain == "" {
+	username := strings.ToLower(usernameAndAccountDomain[0])
+	accountDomain := strings.ToLower(usernameAndAccountDomain[1])
+	if username == "" || accountDomain == "" {
 		l.Debug("aborting request because username or domain was empty")
 		c.JSON(http.StatusBadRequest, gin.H{"error": "bad request"})
 		return
 	}
 
-	if domain != m.config.Host {
-		l.Debugf("aborting request because domain %s does not belong to this instance", domain)
-		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("domain %s does not belong to this instance", domain)})
+	if accountDomain != m.config.AccountDomain {
+		l.Debugf("aborting request because accountDomain %s does not belong to this instance", accountDomain)
+		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("accountDomain %s does not belong to this instance", accountDomain)})
 		return
 	}
 
diff --git a/internal/config/config.go b/internal/config/config.go
index 323b7de81..958926975 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -48,6 +48,7 @@ type Config struct {
 	LogLevel          string             `yaml:"logLevel"`
 	ApplicationName   string             `yaml:"applicationName"`
 	Host              string             `yaml:"host"`
+	AccountDomain     string             `yaml:"accountDomain"`
 	Protocol          string             `yaml:"protocol"`
 	DBConfig          *DBConfig          `yaml:"db"`
 	TemplateConfig    *TemplateConfig    `yaml:"template"`
@@ -133,6 +134,13 @@ func (c *Config) ParseCLIFlags(f KeyedFlags, version string) error {
 		return errors.New("host was not set")
 	}
 
+	if c.AccountDomain == "" || f.IsSet(fn.AccountDomain) {
+		c.AccountDomain = f.String(fn.AccountDomain)
+	}
+	if c.AccountDomain == "" {
+		c.AccountDomain = c.Host // default to whatever the host is, if this is empty
+	}
+
 	if c.Protocol == "" || f.IsSet(fn.Protocol) {
 		c.Protocol = f.String(fn.Protocol)
 	}
@@ -290,6 +298,7 @@ type Flags struct {
 	ApplicationName string
 	ConfigPath      string
 	Host            string
+	AccountDomain   string
 	Protocol        string
 
 	DbType      string
@@ -336,6 +345,7 @@ type Defaults struct {
 	ApplicationName string
 	ConfigPath      string
 	Host            string
+	AccountDomain   string
 	Protocol        string
 	SoftwareVersion string
 
@@ -385,6 +395,7 @@ func GetFlagNames() Flags {
 		ApplicationName: "application-name",
 		ConfigPath:      "config-path",
 		Host:            "host",
+		AccountDomain:   "account-domain",
 		Protocol:        "protocol",
 
 		DbType:      "db-type",
@@ -434,6 +445,7 @@ func GetEnvNames() Flags {
 		ApplicationName: "GTS_APPLICATION_NAME",
 		ConfigPath:      "GTS_CONFIG_PATH",
 		Host:            "GTS_HOST",
+		AccountDomain:   "GTS_ACCOUNT_DOMAIN",
 		Protocol:        "GTS_PROTOCOL",
 
 		DbType:      "GTS_DB_TYPE",
diff --git a/internal/config/default.go b/internal/config/default.go
index 7a030beb5..099eead1c 100644
--- a/internal/config/default.go
+++ b/internal/config/default.go
@@ -118,6 +118,7 @@ func GetDefaults() Defaults {
 		ApplicationName: "gotosocial",
 		ConfigPath:      "",
 		Host:            "",
+		AccountDomain:   "",
 		Protocol:        "https",
 
 		DbType:      "postgres",
@@ -166,6 +167,7 @@ func GetTestDefaults() Defaults {
 		ApplicationName: "gotosocial",
 		ConfigPath:      "",
 		Host:            "localhost:8080",
+		AccountDomain:   "",
 		Protocol:        "http",
 
 		DbType:     "postgres",
diff --git a/internal/processing/federation.go b/internal/processing/federation.go
index 6299d5e7e..966dab08d 100644
--- a/internal/processing/federation.go
+++ b/internal/processing/federation.go
@@ -304,7 +304,7 @@ func (p *processor) GetWebfingerAccount(ctx context.Context, requestedUsername s
 
 	// return the webfinger representation
 	return &apimodel.WellKnownResponse{
-		Subject: fmt.Sprintf("acct:%s@%s", requestedAccount.Username, p.config.Host),
+		Subject: fmt.Sprintf("acct:%s@%s", requestedAccount.Username, p.config.AccountDomain),
 		Aliases: []string{
 			requestedAccount.URI,
 			requestedAccount.URL,
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
index 809cedc45..b24b07e13 100644
--- a/internal/typeutils/internaltoas.go
+++ b/internal/typeutils/internaltoas.go
@@ -580,7 +580,7 @@ func (c *converter) MentionToAS(m *gtsmodel.Mention) (vocab.ActivityStreamsMenti
 	// name -- this should be the namestring of the mentioned user, something like @whatever@example.org
 	var domain string
 	if m.GTSAccount.Domain == "" {
-		domain = c.config.Host
+		domain = c.config.AccountDomain
 	} else {
 		domain = m.GTSAccount.Domain
 	}