summaryrefslogtreecommitdiff
path: root/internal/config/config.go
blob: 21c1ca470720d4a9317ef4f76a02377c7e4f7022 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package config

import (
	"reflect"
	"time"

	"codeberg.org/gruf/go-bytesize"
	"github.com/mitchellh/mapstructure"
)

// cfgtype is the reflected type information of Configuration{}.
var cfgtype = reflect.TypeOf(Configuration{})

// fieldtag will fetch the string value for the given tag name
// on the given field name in the Configuration{} struct.
func fieldtag(field, tag string) string {
	sfield, ok := cfgtype.FieldByName(field)
	if !ok {
		panic("unknown struct field")
	}
	return sfield.Tag.Get(tag)
}

// Configuration represents global GTS server runtime configuration.
//
// Please note that if you update this struct's fields or tags, you
// will need to regenerate the global Getter/Setter helpers by running:
// `go run ./internal/config/gen/ -out ./internal/config/helpers.gen.go`
type Configuration struct {
	LogLevel        string   `name:"log-level" usage:"Log level to run at: [trace, debug, info, warn, fatal]"`
	LogDbQueries    bool     `name:"log-db-queries" usage:"Log database queries verbosely when log-level is trace or debug"`
	ApplicationName string   `name:"application-name" usage:"Name of the application, used in various places internally"`
	LandingPageUser string   `name:"landing-page-user" usage:"the user that should be shown on the instance's landing page"`
	ConfigPath      string   `name:"config-path" usage:"Path to a file containing gotosocial configuration. Values set in this file will be overwritten by values set as env vars or arguments"`
	Host            string   `name:"host" usage:"Hostname to use for the server (eg., example.org, gotosocial.whatever.com). DO NOT change this on a server that's already run!"`
	AccountDomain   string   `name:"account-domain" 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!"`
	Protocol        string   `name:"protocol" usage:"Protocol to use for the REST api of the server (only use http if you are debugging or behind a reverse proxy!)"`
	BindAddress     string   `name:"bind-address" usage:"Bind address to use for the GoToSocial server (eg., 0.0.0.0, 172.138.0.9, [::], localhost). For ipv6, enclose the address in square brackets, eg [2001:db8::fed1]. Default binds to all interfaces."`
	Port            int      `name:"port" usage:"Port to use for GoToSocial. Change this to 443 if you're running the binary directly on the host machine."`
	TrustedProxies  []string `name:"trusted-proxies" usage:"Proxies to trust when parsing x-forwarded headers into real IPs."`
	SoftwareVersion string   `name:"software-version" usage:""`

	DbType                   string        `name:"db-type" usage:"Database type: eg., postgres"`
	DbAddress                string        `name:"db-address" usage:"Database ipv4 address, hostname, or filename"`
	DbPort                   int           `name:"db-port" usage:"Database port"`
	DbUser                   string        `name:"db-user" usage:"Database username"`
	DbPassword               string        `name:"db-password" usage:"Database password"`
	DbDatabase               string        `name:"db-database" usage:"Database name"`
	DbTLSMode                string        `name:"db-tls-mode" usage:"Database tls mode"`
	DbTLSCACert              string        `name:"db-tls-ca-cert" usage:"Path to CA cert for db tls connection"`
	DbMaxOpenConnsMultiplier int           `name:"db-max-open-conns-multiplier" usage:"Multiplier to use per cpu for max open database connections. 0 or less is normalized to 1."`
	DbSqliteJournalMode      string        `name:"db-sqlite-journal-mode" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_journal_mode"`
	DbSqliteSynchronous      string        `name:"db-sqlite-synchronous" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_synchronous"`
	DbSqliteCacheSize        bytesize.Size `name:"db-sqlite-cache-size" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_cache_size"`
	DbSqliteBusyTimeout      time.Duration `name:"db-sqlite-busy-timeout" usage:"Sqlite only: see https://www.sqlite.org/pragma.html#pragma_busy_timeout"`

	WebTemplateBaseDir string `name:"web-template-base-dir" usage:"Basedir for html templating files for rendering pages and composing emails."`
	WebAssetBaseDir    string `name:"web-asset-base-dir" usage:"Directory to serve static assets from, accessible at example.org/assets/"`

	InstanceExposePeers            bool `name:"instance-expose-peers" usage:"Allow unauthenticated users to query /api/v1/instance/peers?filter=open"`
	InstanceExposeSuspended        bool `name:"instance-expose-suspended" usage:"Expose suspended instances via web UI, and allow unauthenticated users to query /api/v1/instance/peers?filter=suspended"`
	InstanceExposeSuspendedWeb     bool `name:"instance-expose-suspended-web" usage:"Expose list of suspended instances as webpage on /about/suspended"`
	InstanceExposePublicTimeline   bool `name:"instance-expose-public-timeline" usage:"Allow unauthenticated users to query /api/v1/timelines/public"`
	InstanceDeliverToSharedInboxes bool `name:"instance-deliver-to-shared-inboxes" usage:"Deliver federated messages to shared inboxes, if they're available."`

	AccountsRegistrationOpen bool `name:"accounts-registration-open" usage:"Allow anyone to submit an account signup request. If false, server will be invite-only."`
	AccountsApprovalRequired bool `name:"accounts-approval-required" usage:"Do account signups require approval by an admin or moderator before user can log in? If false, new registrations will be automatically approved."`
	AccountsReasonRequired   bool `name:"accounts-reason-required" usage:"Do new account signups require a reason to be submitted on registration?"`
	AccountsAllowCustomCSS   bool `name:"accounts-allow-custom-css" usage:"Allow accounts to enable custom CSS for their profile pages and statuses."`

	MediaImageMaxSize        bytesize.Size `name:"media-image-max-size" usage:"Max size of accepted images in bytes"`
	MediaVideoMaxSize        bytesize.Size `name:"media-video-max-size" usage:"Max size of accepted videos in bytes"`
	MediaDescriptionMinChars int           `name:"media-description-min-chars" usage:"Min required chars for an image description"`
	MediaDescriptionMaxChars int           `name:"media-description-max-chars" usage:"Max permitted chars for an image description"`
	MediaRemoteCacheDays     int           `name:"media-remote-cache-days" usage:"Number of days to locally cache media from remote instances. If set to 0, remote media will be kept indefinitely."`
	MediaEmojiLocalMaxSize   bytesize.Size `name:"media-emoji-local-max-size" usage:"Max size in bytes of emojis uploaded to this instance via the admin API."`
	MediaEmojiRemoteMaxSize  bytesize.Size `name:"media-emoji-remote-max-size" usage:"Max size in bytes of emojis to download from other instances."`

	StorageBackend       string `name:"storage-backend" usage:"Storage backend to use for media attachments"`
	StorageLocalBasePath string `name:"storage-local-base-path" usage:"Full path to an already-created directory where gts should store/retrieve media files. Subfolders will be created within this dir."`
	StorageS3Endpoint    string `name:"storage-s3-endpoint" usage:"S3 Endpoint URL (e.g 'minio.example.org:9000')"`
	StorageS3AccessKey   string `name:"storage-s3-access-key" usage:"S3 Access Key"`
	StorageS3SecretKey   string `name:"storage-s3-secret-key" usage:"S3 Secret Key"`
	StorageS3UseSSL      bool   `name:"storage-s3-use-ssl" usage:"Use SSL for S3 connections. Only set this to 'false' when testing locally"`
	StorageS3BucketName  string `name:"storage-s3-bucket" usage:"Place blobs in this bucket"`
	StorageS3Proxy       bool   `name:"storage-s3-proxy" usage:"Proxy S3 contents through GoToSocial instead of redirecting to a presigned URL"`

	StatusesMaxChars           int `name:"statuses-max-chars" usage:"Max permitted characters for posted statuses"`
	StatusesCWMaxChars         int `name:"statuses-cw-max-chars" usage:"Max permitted characters for content/spoiler warnings on statuses"`
	StatusesPollMaxOptions     int `name:"statuses-poll-max-options" usage:"Max amount of options permitted on a poll"`
	StatusesPollOptionMaxChars int `name:"statuses-poll-option-max-chars" usage:"Max amount of characters for a poll option"`
	StatusesMediaMaxFiles      int `name:"statuses-media-max-files" usage:"Maximum number of media files/attachments per status"`

	LetsEncryptEnabled      bool   `name:"letsencrypt-enabled" usage:"Enable letsencrypt TLS certs for this server. If set to true, then cert dir also needs to be set (or take the default)."`
	LetsEncryptPort         int    `name:"letsencrypt-port" usage:"Port to listen on for letsencrypt certificate challenges. Must not be the same as the GtS webserver/API port."`
	LetsEncryptCertDir      string `name:"letsencrypt-cert-dir" usage:"Directory to store acquired letsencrypt certificates."`
	LetsEncryptEmailAddress string `name:"letsencrypt-email-address" usage:"Email address to use when requesting letsencrypt certs. Will receive updates on cert expiry etc."`

	TLSCertificateChain string `name:"tls-certificate-chain" usage:"Filesystem path to the certificate chain including any intermediate CAs and the TLS public key"`
	TLSCertificateKey   string `name:"tls-certificate-key" usage:"Filesystem path to the TLS private key"`

	OIDCEnabled          bool     `name:"oidc-enabled" usage:"Enabled OIDC authorization for this instance. If set to true, then the other OIDC flags must also be set."`
	OIDCIdpName          string   `name:"oidc-idp-name" usage:"Name of the OIDC identity provider. Will be shown to the user when logging in."`
	OIDCSkipVerification bool     `name:"oidc-skip-verification" usage:"Skip verification of tokens returned by the OIDC provider. Should only be set to 'true' for testing purposes, never in a production environment!"`
	OIDCIssuer           string   `name:"oidc-issuer" usage:"Address of the OIDC issuer. Should be the web address, including protocol, at which the issuer can be reached. Eg., 'https://example.org/auth'"`
	OIDCClientID         string   `name:"oidc-client-id" usage:"ClientID of GoToSocial, as registered with the OIDC provider."`
	OIDCClientSecret     string   `name:"oidc-client-secret" usage:"ClientSecret of GoToSocial, as registered with the OIDC provider."`
	OIDCScopes           []string `name:"oidc-scopes" usage:"OIDC scopes."`
	OIDCLinkExisting     bool     `name:"oidc-link-existing" usage:"link existing user accounts to OIDC logins based on the stored email value"`
	OIDCAdminGroups      []string `name:"oidc-admin-groups" usage:"Membership of one of the listed groups makes someone a GtS admin"`

	SMTPHost     string `name:"smtp-host" usage:"Host of the smtp server. Eg., 'smtp.eu.mailgun.org'"`
	SMTPPort     int    `name:"smtp-port" usage:"Port of the smtp server. Eg., 587"`
	SMTPUsername string `name:"smtp-username" usage:"Username to authenticate with the smtp server as. Eg., 'postmaster@mail.example.org'"`
	SMTPPassword string `name:"smtp-password" usage:"Password to pass to the smtp server."`
	SMTPFrom     string `name:"smtp-from" usage:"Address to use as the 'from' field of the email. Eg., 'gotosocial@example.org'"`

	SyslogEnabled  bool   `name:"syslog-enabled" usage:"Enable the syslog logging hook. Logs will be mirrored to the configured destination."`
	SyslogProtocol string `name:"syslog-protocol" usage:"Protocol to use when directing logs to syslog. Leave empty to connect to local syslog."`
	SyslogAddress  string `name:"syslog-address" usage:"Address:port to send syslog logs to. Leave empty to connect to local syslog."`

	AdvancedCookiesSamesite      string        `name:"advanced-cookies-samesite" usage:"'strict' or 'lax', see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite"`
	AdvancedRateLimitRequests    int           `name:"advanced-rate-limit-requests" usage:"Amount of HTTP requests to permit within a 5 minute window. 0 or less turns rate limiting off."`
	AdvancedThrottlingMultiplier int           `name:"advanced-throttling-multiplier" usage:"Multiplier to use per cpu for http request throttling. 0 or less turns throttling off."`
	AdvancedThrottlingRetryAfter time.Duration `name:"advanced-throttling-retry-after" usage:"Retry-After duration response to send for throttled requests."`

	// Cache configuration vars.
	Cache CacheConfiguration `name:"cache"`

	// TODO: move these elsewhere, these are more ephemeral vs long-running flags like above
	AdminAccountUsername  string `name:"username" usage:"the username to create/delete/etc"`
	AdminAccountEmail     string `name:"email" usage:"the email address of this account"`
	AdminAccountPassword  string `name:"password" usage:"the password to set for this account"`
	AdminTransPath        string `name:"path" usage:"the path of the file to import from/export to"`
	AdminMediaPruneDryRun bool   `name:"dry-run" usage:"perform a dry run and only log number of items eligible for pruning"`

	RequestIDHeader string `name:"request-id-header" usage:"Header to extract the Request ID from. Eg.,'X-Request-Id'"`
}

type CacheConfiguration struct {
	GTS GTSCacheConfiguration `name:"gts"`
}

type GTSCacheConfiguration struct {
	AccountMaxSize   int           `name:"account-max-size"`
	AccountTTL       time.Duration `name:"account-ttl"`
	AccountSweepFreq time.Duration `name:"account-sweep-freq"`

	BlockMaxSize   int           `name:"block-max-size"`
	BlockTTL       time.Duration `name:"block-ttl"`
	BlockSweepFreq time.Duration `name:"block-sweep-freq"`

	DomainBlockMaxSize   int           `name:"domain-block-max-size"`
	DomainBlockTTL       time.Duration `name:"domain-block-ttl"`
	DomainBlockSweepFreq time.Duration `name:"domain-block-sweep-freq"`

	EmojiMaxSize   int           `name:"emoji-max-size"`
	EmojiTTL       time.Duration `name:"emoji-ttl"`
	EmojiSweepFreq time.Duration `name:"emoji-sweep-freq"`

	EmojiCategoryMaxSize   int           `name:"emoji-category-max-size"`
	EmojiCategoryTTL       time.Duration `name:"emoji-category-ttl"`
	EmojiCategorySweepFreq time.Duration `name:"emoji-category-sweep-freq"`

	MediaMaxSize   int           `name:"media-max-size"`
	MediaTTL       time.Duration `name:"media-ttl"`
	MediaSweepFreq time.Duration `name:"media-sweep-freq"`

	MentionMaxSize   int           `name:"mention-max-size"`
	MentionTTL       time.Duration `name:"mention-ttl"`
	MentionSweepFreq time.Duration `name:"mention-sweep-freq"`

	NotificationMaxSize   int           `name:"notification-max-size"`
	NotificationTTL       time.Duration `name:"notification-ttl"`
	NotificationSweepFreq time.Duration `name:"notification-sweep-freq"`

	ReportMaxSize   int           `name:"report-max-size"`
	ReportTTL       time.Duration `name:"report-ttl"`
	ReportSweepFreq time.Duration `name:"report-sweep-freq"`

	StatusMaxSize   int           `name:"status-max-size"`
	StatusTTL       time.Duration `name:"status-ttl"`
	StatusSweepFreq time.Duration `name:"status-sweep-freq"`

	TombstoneMaxSize   int           `name:"tombstone-max-size"`
	TombstoneTTL       time.Duration `name:"tombstone-ttl"`
	TombstoneSweepFreq time.Duration `name:"tombstone-sweep-freq"`

	UserMaxSize   int           `name:"user-max-size"`
	UserTTL       time.Duration `name:"user-ttl"`
	UserSweepFreq time.Duration `name:"user-sweep-freq"`

	WebfingerMaxSize   int           `name:"webfinger-max-size"`
	WebfingerTTL       time.Duration `name:"webfinger-ttl"`
	WebfingerSweepFreq time.Duration `name:"webfinger-sweep-freq"`
}

// MarshalMap will marshal current Configuration into a map structure (useful for JSON/TOML/YAML).
func (cfg *Configuration) MarshalMap() (map[string]interface{}, error) {
	var dst map[string]interface{}
	dec, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		TagName: "name",
		Result:  &dst,
	})
	if err := dec.Decode(cfg); err != nil {
		return nil, err
	}
	return dst, nil
}