2014-04-10 14:20:58 -04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2017-05-29 09:17:15 +02:00
// Copyright 2017 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2014-04-10 14:20:58 -04:00
2014-05-25 20:11:25 -04:00
package setting
2014-04-10 14:20:58 -04:00
import (
2019-04-02 08:48:31 +01:00
"fmt"
2014-04-10 14:20:58 -04:00
"os"
2019-04-28 21:48:46 +02:00
"runtime"
2014-04-10 14:20:58 -04:00
"strings"
2014-07-24 22:31:59 +02:00
"time"
2014-04-10 14:20:58 -04:00
2016-12-22 19:12:23 +01:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/user"
2024-03-14 16:44:49 +08:00
"code.gitea.io/gitea/modules/util"
2014-04-10 14:20:58 -04:00
)
2016-11-27 18:14:25 +08:00
// settings
2014-04-10 14:20:58 -04:00
var (
2021-02-19 21:36:43 +00:00
// AppVer is the version of the current build of Gitea. It is set in main.go from main.Version.
AppVer string
2023-04-19 21:40:42 +08:00
// AppBuiltWith represents a human-readable version go runtime build version and build tags. (See main.go formatBuiltWith().)
2021-02-19 21:36:43 +00:00
AppBuiltWith string
// AppStartTime store time gitea has started
AppStartTime time . Time
2023-02-20 00:12:01 +08:00
2023-04-19 21:40:42 +08:00
// Other global setting objects
2023-03-16 15:22:54 +08:00
CfgProvider ConfigProvider
RunMode string
RunUser string
IsProd bool
IsWindows bool
2023-04-19 21:40:42 +08:00
// IsInTesting indicates whether the testing is running. A lot of unreliable code causes a lot of nonsense error logs during testing
// TODO: this is only a temporary solution, we should make the test code more reliable
IsInTesting = false
2014-04-10 14:20:58 -04:00
)
2015-11-08 16:59:56 -05:00
func init ( ) {
2019-04-28 21:48:46 +02:00
IsWindows = runtime . GOOS == "windows"
2023-04-19 21:40:42 +08:00
if AppVer == "" {
AppVer = "dev"
}
2019-04-02 08:48:31 +01:00
// We can rely on log.CanColorStdout being set properly because modules/log/console_windows.go comes before modules/setting/setting.go lexicographically
2023-04-19 21:40:42 +08:00
// By default set this logger at Info - we'll change it later, but we need to start with something.
2023-05-22 06:35:11 +08:00
log . SetConsoleLogger ( log . DEFAULT , "console" , log . INFO )
2014-05-25 20:11:25 -04:00
}
2016-08-09 17:41:18 -07:00
// IsRunUserMatchCurrentUser returns false if configured run user does not match
// actual user that runs the app. The first return value is the actual user name.
// This check is ignored under Windows since SSH remote login is not the main
// method to login on Windows.
func IsRunUserMatchCurrentUser ( runUser string ) ( string , bool ) {
2019-06-16 04:49:07 +02:00
if IsWindows || SSH . StartBuiltinServer {
2016-08-09 17:41:18 -07:00
return "" , true
}
currentUser := user . CurrentUsername ( )
return currentUser , runUser == currentUser
}
2023-02-20 00:12:01 +08:00
// PrepareAppDataPath creates app data directory if necessary
func PrepareAppDataPath ( ) error {
// FIXME: There are too many calls to MkdirAll in old code. It is incorrect.
// For example, if someDir=/mnt/vol1/gitea-home/data, if the mount point /mnt/vol1 is not mounted when Gitea runs,
// then gitea will make new empty directories in /mnt/vol1, all are stored in the root filesystem.
// The correct behavior should be: creating parent directories is end users' duty. We only create sub-directories in existing parent directories.
// For quickstart, the parent directories should be created automatically for first startup (eg: a flag or a check of INSTALL_LOCK).
// Now we can take the first step to do correctly (using Mkdir) in other packages, and prepare the AppDataPath here, then make a refactor in future.
st , err := os . Stat ( AppDataPath )
if os . IsNotExist ( err ) {
err = os . MkdirAll ( AppDataPath , os . ModePerm )
if err != nil {
return fmt . Errorf ( "unable to create the APP_DATA_PATH directory: %q, Error: %w" , AppDataPath , err )
}
return nil
}
2021-12-01 15:50:01 +08:00
2023-02-20 00:12:01 +08:00
if err != nil {
return fmt . Errorf ( "unable to use APP_DATA_PATH %q. Error: %w" , AppDataPath , err )
}
2021-12-01 15:50:01 +08:00
2023-02-20 00:12:01 +08:00
if ! st . IsDir ( ) /* also works for symlink */ {
return fmt . Errorf ( "the APP_DATA_PATH %q is not a directory (or symlink to a directory) and can't be used" , AppDataPath )
2021-12-01 15:50:01 +08:00
}
2023-02-20 00:12:01 +08:00
return nil
2021-12-01 15:50:01 +08:00
}
2024-02-08 20:31:38 +08:00
func InitCfgProvider ( file string ) {
2023-04-25 23:06:39 +08:00
var err error
2024-02-08 20:31:38 +08:00
if CfgProvider , err = NewConfigProviderFromFile ( file ) ; err != nil {
2023-06-21 13:50:26 +08:00
log . Fatal ( "Unable to init config provider from %q: %v" , file , err )
}
2023-06-21 10:31:40 +08:00
CfgProvider . DisableSaving ( ) // do not allow saving the CfgProvider into file, it will be polluted by the "MustXxx" calls
2023-06-21 13:50:26 +08:00
}
func MustInstalled ( ) {
if ! InstallLock {
log . Fatal ( ` Unable to load config file for a installed Gitea instance, you should either use "--config" to set your config file (app.ini), or run "gitea web" command to install Gitea. ` )
2023-04-25 23:06:39 +08:00
}
2023-06-21 13:50:26 +08:00
}
func LoadCommonSettings ( ) {
if err := loadCommonSettingsFrom ( CfgProvider ) ; err != nil {
log . Fatal ( "Unable to load settings from config: %v" , err )
2022-10-17 07:29:26 +08:00
}
2023-02-20 00:12:01 +08:00
}
2019-08-15 22:46:21 +08:00
2023-02-20 00:12:01 +08:00
// loadCommonSettingsFrom loads common configurations from a configuration provider.
2023-06-14 11:42:38 +08:00
func loadCommonSettingsFrom ( cfg ConfigProvider ) error {
2023-06-21 10:31:40 +08:00
// WARNING: don't change the sequence except you know what you are doing.
2023-02-20 00:12:01 +08:00
loadRunModeFrom ( cfg )
2023-05-22 06:35:11 +08:00
loadLogGlobalFrom ( cfg )
2023-02-20 00:12:01 +08:00
loadServerFrom ( cfg )
loadSSHFrom ( cfg )
2023-05-01 02:14:57 +08:00
mustCurrentRunUserMatch ( cfg ) // it depends on the SSH config, only non-builtin SSH server requires this check
2023-02-20 00:12:01 +08:00
loadOAuth2From ( cfg )
loadSecurityFrom ( cfg )
2023-06-14 11:42:38 +08:00
if err := loadAttachmentFrom ( cfg ) ; err != nil {
return err
}
if err := loadLFSFrom ( cfg ) ; err != nil {
return err
}
2023-02-20 00:12:01 +08:00
loadTimeFrom ( cfg )
loadRepositoryFrom ( cfg )
2023-06-14 11:42:38 +08:00
if err := loadAvatarsFrom ( cfg ) ; err != nil {
return err
}
if err := loadRepoAvatarFrom ( cfg ) ; err != nil {
return err
}
if err := loadPackagesFrom ( cfg ) ; err != nil {
return err
}
if err := loadActionsFrom ( cfg ) ; err != nil {
return err
}
2023-02-20 00:12:01 +08:00
loadUIFrom ( cfg )
loadAdminFrom ( cfg )
loadAPIFrom ( cfg )
loadMetricsFrom ( cfg )
loadCamoFrom ( cfg )
loadI18nFrom ( cfg )
loadGitFrom ( cfg )
loadMirrorFrom ( cfg )
loadMarkupFrom ( cfg )
loadOtherFrom ( cfg )
2023-06-14 11:42:38 +08:00
return nil
2023-02-20 00:12:01 +08:00
}
2014-07-24 22:31:59 +02:00
2023-02-20 00:12:01 +08:00
func loadRunModeFrom ( rootCfg ConfigProvider ) {
rootSec := rootCfg . Section ( "" )
RunUser = rootSec . Key ( "RUN_USER" ) . MustString ( user . CurrentUsername ( ) )
2024-03-14 16:44:49 +08:00
2021-10-07 04:52:08 -04:00
// The following is a purposefully undocumented option. Please do not run Gitea as root. It will only cause future headaches.
// Please don't use root as a bandaid to "fix" something that is broken, instead the broken thing should instead be fixed properly.
2023-06-19 00:10:44 +08:00
unsafeAllowRunAsRoot := ConfigSectionKeyBool ( rootSec , "I_AM_BEING_UNSAFE_RUNNING_AS_ROOT" )
2024-03-14 16:44:49 +08:00
unsafeAllowRunAsRoot = unsafeAllowRunAsRoot || util . OptionalBoolParse ( os . Getenv ( "GITEA_I_AM_BEING_UNSAFE_RUNNING_AS_ROOT" ) ) . Value ( )
2022-12-27 14:00:34 +08:00
RunMode = os . Getenv ( "GITEA_RUN_MODE" )
if RunMode == "" {
2023-02-20 00:12:01 +08:00
RunMode = rootSec . Key ( "RUN_MODE" ) . MustString ( "prod" )
2022-12-27 14:00:34 +08:00
}
2023-05-25 11:47:30 +08:00
// non-dev mode is treated as prod mode, to protect users from accidentally running in dev mode if there is a typo in this value.
RunMode = strings . ToLower ( RunMode )
if RunMode != "dev" {
RunMode = "prod"
}
IsProd = RunMode != "dev"
2014-05-25 20:11:25 -04:00
2021-10-07 04:52:08 -04:00
// check if we run as root
if os . Getuid ( ) == 0 {
if ! unsafeAllowRunAsRoot {
// Special thanks to VLC which inspired the wording of this messaging.
log . Fatal ( "Gitea is not supposed to be run as root. Sorry. If you need to use privileged TCP ports please instead use setcap and the `cap_net_bind_service` permission" )
}
log . Critical ( "You are running Gitea using the root user, and have purposely chosen to skip built-in protections around this. You have been warned against this." )
}
2020-12-22 12:13:50 +01:00
}
2023-07-10 06:43:37 +08:00
// HasInstallLock checks the install-lock in ConfigProvider directly, because sometimes the config file is not loaded into setting variables yet.
func HasInstallLock ( rootCfg ConfigProvider ) bool {
return rootCfg . Section ( "security" ) . Key ( "INSTALL_LOCK" ) . MustBool ( false )
}
2023-05-01 02:14:57 +08:00
func mustCurrentRunUserMatch ( rootCfg ConfigProvider ) {
// Does not check run user when the "InstallLock" is off.
2023-07-10 06:43:37 +08:00
if HasInstallLock ( rootCfg ) {
2023-05-01 02:14:57 +08:00
currentUser , match := IsRunUserMatchCurrentUser ( RunUser )
if ! match {
log . Fatal ( "Expect user '%s' but current user is: %s" , RunUser , currentUser )
}
}
}
2023-02-20 00:12:01 +08:00
// LoadSettings initializes the settings for normal start up
func LoadSettings ( ) {
2023-05-22 06:35:11 +08:00
initAllLoggers ( )
2023-03-16 15:22:54 +08:00
loadDBSetting ( CfgProvider )
2023-02-20 00:12:01 +08:00
loadServiceFrom ( CfgProvider )
loadOAuth2ClientFrom ( CfgProvider )
loadCacheFrom ( CfgProvider )
loadSessionFrom ( CfgProvider )
loadCorsFrom ( CfgProvider )
loadMailsFrom ( CfgProvider )
loadProxyFrom ( CfgProvider )
loadWebhookFrom ( CfgProvider )
loadMigrationsFrom ( CfgProvider )
loadIndexerFrom ( CfgProvider )
loadTaskFrom ( CfgProvider )
LoadQueueSettings ( )
loadProjectFrom ( CfgProvider )
loadMimeTypeMapFrom ( CfgProvider )
loadFederationFrom ( CfgProvider )
2014-04-10 14:20:58 -04:00
}
2021-06-17 00:32:57 +01:00
2023-02-20 00:12:01 +08:00
// LoadSettingsForInstall initializes the settings for install
func LoadSettingsForInstall ( ) {
2023-03-16 15:22:54 +08:00
loadDBSetting ( CfgProvider )
2023-02-20 00:12:01 +08:00
loadServiceFrom ( CfgProvider )
loadMailerFrom ( CfgProvider )
2021-06-17 00:32:57 +01:00
}
2024-02-09 22:06:03 +08:00
var uniquePaths = make ( map [ string ] string )
func fatalDuplicatedPath ( name , p string ) {
if targetName , ok := uniquePaths [ p ] ; ok && targetName != name {
log . Fatal ( "storage path %q is being used by %q and %q and all storage paths must be unique to prevent data loss." , p , targetName , name )
}
uniquePaths [ p ] = name
}