summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2023-07-10 06:43:37 +0800
committerGitHub <noreply@github.com>2023-07-09 22:43:37 +0000
commitfa0b5b14c2faa6a5f76bb2e7bc9241a5e4354189 (patch)
tree885a32e803e934883ca047116441f56ac9435b5b
parent61e0d1a767e1a1a509de9de4aff42bdb79cc6443 (diff)
downloadgitea-fa0b5b14c2faa6a5f76bb2e7bc9241a5e4354189.tar.gz
gitea-fa0b5b14c2faa6a5f76bb2e7bc9241a5e4354189.zip
Make "install page" respect environment config (#25648)
Replace #25580 Fix #19453 The problem was: when users set "GITEA__XXX__YYY" , the "install page" doesn't respect it. So, to make the result consistent and avoid surprising end users, now the "install page" also writes the environment variables to the config file. And, to make things clear, there are enough messages on the UI to tell users what will happen. There are some necessary/related changes to `environment-to-ini.go`: * The "--clear" flag is removed and it was incorrectly written there. The "clear" operation should be done if INSTALL_LOCK=true * The "--prefix" flag is removed because it's never used, never documented and it only causes inconsistent behavior. ![image](https://github.com/go-gitea/gitea/assets/2114189/12778ee4-3fb5-4664-a73a-41ebbd77cd5b)
-rw-r--r--contrib/environment-to-ini/environment-to-ini.go31
-rw-r--r--docs/content/doc/installation/with-docker-rootless.en-us.md2
-rw-r--r--docs/content/doc/installation/with-docker.en-us.md2
-rw-r--r--modules/assetfs/layered.go1
-rw-r--r--modules/setting/config_env.go25
-rw-r--r--modules/setting/config_env_test.go8
-rw-r--r--modules/setting/path.go3
-rw-r--r--modules/setting/security.go2
-rw-r--r--modules/setting/setting.go8
-rw-r--r--options/locale/locale_en-US.ini2
-rw-r--r--routers/install/install.go18
-rw-r--r--templates/install.tmpl31
-rw-r--r--web_src/css/install.css25
13 files changed, 86 insertions, 72 deletions
diff --git a/contrib/environment-to-ini/environment-to-ini.go b/contrib/environment-to-ini/environment-to-ini.go
index 230ed58269..e472384a95 100644
--- a/contrib/environment-to-ini/environment-to-ini.go
+++ b/contrib/environment-to-ini/environment-to-ini.go
@@ -5,7 +5,6 @@ package main
import (
"os"
- "strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -13,9 +12,6 @@ import (
"github.com/urfave/cli"
)
-// EnvironmentPrefix environment variables prefixed with this represent ini values to write
-const EnvironmentPrefix = "GITEA"
-
func main() {
app := cli.NewApp()
app.Name = "environment-to-ini"
@@ -70,15 +66,6 @@ func main() {
Value: "",
Usage: "Destination file to write to",
},
- cli.BoolFlag{
- Name: "clear",
- Usage: "Clears the matched variables from the environment",
- },
- cli.StringFlag{
- Name: "prefix, p",
- Value: EnvironmentPrefix,
- Usage: "Environment prefix to look for - will be suffixed by __ (2 underscores)",
- },
}
app.Action = runEnvironmentToIni
err := app.Run(os.Args)
@@ -99,9 +86,7 @@ func runEnvironmentToIni(c *cli.Context) error {
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
}
- prefixGitea := c.String("prefix") + "__"
- suffixFile := "__FILE"
- changed := setting.EnvironmentToConfig(cfg, prefixGitea, suffixFile, os.Environ())
+ changed := setting.EnvironmentToConfig(cfg, os.Environ())
// try to save the config file
destination := c.String("out")
@@ -116,19 +101,5 @@ func runEnvironmentToIni(c *cli.Context) error {
}
}
- // clear Gitea's specific environment variables if requested
- if c.Bool("clear") {
- for _, kv := range os.Environ() {
- idx := strings.IndexByte(kv, '=')
- if idx < 0 {
- continue
- }
- eKey := kv[:idx]
- if strings.HasPrefix(eKey, prefixGitea) {
- _ = os.Unsetenv(eKey)
- }
- }
- }
-
return nil
}
diff --git a/docs/content/doc/installation/with-docker-rootless.en-us.md b/docs/content/doc/installation/with-docker-rootless.en-us.md
index b8b40fcbd7..5aa4e46e12 100644
--- a/docs/content/doc/installation/with-docker-rootless.en-us.md
+++ b/docs/content/doc/installation/with-docker-rootless.en-us.md
@@ -288,7 +288,7 @@ docker-compose up -d
In addition to the environment variables above, any settings in `app.ini` can be set
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
-These settings are applied each time the docker container starts.
+These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
Full information [here](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini).
These environment variables can be passed to the docker container in `docker-compose.yml`.
diff --git a/docs/content/doc/installation/with-docker.en-us.md b/docs/content/doc/installation/with-docker.en-us.md
index e70a6ab133..a7a575293d 100644
--- a/docs/content/doc/installation/with-docker.en-us.md
+++ b/docs/content/doc/installation/with-docker.en-us.md
@@ -289,7 +289,7 @@ docker-compose up -d
In addition to the environment variables above, any settings in `app.ini` can be set
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
-These settings are applied each time the docker container starts.
+These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
Full information [here](https://github.com/go-gitea/gitea/tree/master/contrib/environment-to-ini).
These environment variables can be passed to the docker container in `docker-compose.yml`.
diff --git a/modules/assetfs/layered.go b/modules/assetfs/layered.go
index d032160a6f..e18a13e4aa 100644
--- a/modules/assetfs/layered.go
+++ b/modules/assetfs/layered.go
@@ -215,6 +215,7 @@ func (l *LayeredFS) WatchLocalChanges(ctx context.Context, callback func()) {
log.Error("Unable to list directories for asset local file-system %q: %v", layer.localPath, err)
continue
}
+ layerDirs = append(layerDirs, ".")
for _, dir := range layerDirs {
if err = watcher.Add(util.FilePathJoinAbs(layer.localPath, dir)); err != nil {
log.Error("Unable to watch directory %s: %v", dir, err)
diff --git a/modules/setting/config_env.go b/modules/setting/config_env.go
index 6348803705..e23b64557f 100644
--- a/modules/setting/config_env.go
+++ b/modules/setting/config_env.go
@@ -12,10 +12,31 @@ import (
"code.gitea.io/gitea/modules/log"
)
+const (
+ EnvConfigKeyPrefixGitea = "GITEA__"
+ EnvConfigKeySuffixFile = "__FILE"
+)
+
const escapeRegexpString = "_0[xX](([0-9a-fA-F][0-9a-fA-F])+)_"
var escapeRegex = regexp.MustCompile(escapeRegexpString)
+func CollectEnvConfigKeys() (keys []string) {
+ for _, env := range os.Environ() {
+ if strings.HasPrefix(env, EnvConfigKeyPrefixGitea) {
+ k, _, _ := strings.Cut(env, "=")
+ keys = append(keys, k)
+ }
+ }
+ return keys
+}
+
+func ClearEnvConfigKeys() {
+ for _, k := range CollectEnvConfigKeys() {
+ _ = os.Unsetenv(k)
+ }
+}
+
// decodeEnvSectionKey will decode a portable string encoded Section__Key pair
// Portable strings are considered to be of the form [A-Z0-9_]*
// We will encode a disallowed value as the UTF8 byte string preceded by _0X and
@@ -87,7 +108,7 @@ func decodeEnvironmentKey(prefixGitea, suffixFile, envKey string) (ok bool, sect
return ok, section, key, useFileValue
}
-func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, envs []string) (changed bool) {
+func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) {
for _, kv := range envs {
idx := strings.IndexByte(kv, '=')
if idx < 0 {
@@ -97,7 +118,7 @@ func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, env
// parse the environment variable to config section name and key name
envKey := kv[:idx]
envValue := kv[idx+1:]
- ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixGitea, suffixFile, envKey)
+ ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(EnvConfigKeyPrefixGitea, EnvConfigKeySuffixFile, envKey)
if !ok {
continue
}
diff --git a/modules/setting/config_env_test.go b/modules/setting/config_env_test.go
index d574554bcc..2c1dd2f5c7 100644
--- a/modules/setting/config_env_test.go
+++ b/modules/setting/config_env_test.go
@@ -72,7 +72,7 @@ func TestDecodeEnvironmentKey(t *testing.T) {
func TestEnvironmentToConfig(t *testing.T) {
cfg, _ := NewConfigProviderFromData("")
- changed := EnvironmentToConfig(cfg, "GITEA__", "__FILE", nil)
+ changed := EnvironmentToConfig(cfg, nil)
assert.False(t, changed)
cfg, err := NewConfigProviderFromData(`
@@ -81,16 +81,16 @@ key = old
`)
assert.NoError(t, err)
- changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
+ changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key=new"})
assert.True(t, changed)
assert.Equal(t, "new", cfg.Section("sec").Key("key").String())
- changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
+ changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key=new"})
assert.False(t, changed)
tmpFile := t.TempDir() + "/the-file"
_ = os.WriteFile(tmpFile, []byte("value-from-file"), 0o644)
- changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key__FILE=" + tmpFile})
+ changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.True(t, changed)
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
}
diff --git a/modules/setting/path.go b/modules/setting/path.go
index 163f1d1590..32ed8d81fa 100644
--- a/modules/setting/path.go
+++ b/modules/setting/path.go
@@ -171,6 +171,9 @@ func InitWorkPathAndCfgProvider(getEnvFn func(name string) string, args ArgWorkP
// only read the config but do not load/init anything more, because the AppWorkPath and CustomPath are not ready
InitCfgProvider(tmpCustomConf.Value)
+ if HasInstallLock(CfgProvider) {
+ ClearEnvConfigKeys() // if the instance has been installed, do not pass the environment variables to sub-processes
+ }
configWorkPath := ConfigSectionKeyString(CfgProvider.Section(""), "WORK_PATH")
if configWorkPath != "" {
if !filepath.IsAbs(configWorkPath) {
diff --git a/modules/setting/security.go b/modules/setting/security.go
index 5f1f9f4ade..7064d7a008 100644
--- a/modules/setting/security.go
+++ b/modules/setting/security.go
@@ -102,7 +102,7 @@ func generateSaveInternalToken(rootCfg ConfigProvider) {
func loadSecurityFrom(rootCfg ConfigProvider) {
sec := rootCfg.Section("security")
- InstallLock = sec.Key("INSTALL_LOCK").MustBool(false)
+ InstallLock = HasInstallLock(rootCfg)
LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt(7)
CookieUserName = sec.Key("COOKIE_USERNAME").MustString("gitea_awesome")
SecretKey = loadSecret(sec, "SECRET_KEY_URI", "SECRET_KEY")
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 0d69847dbe..d444d9a017 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -183,10 +183,14 @@ func loadRunModeFrom(rootCfg ConfigProvider) {
}
}
+// 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)
+}
+
func mustCurrentRunUserMatch(rootCfg ConfigProvider) {
// Does not check run user when the "InstallLock" is off.
- installLock := rootCfg.Section("security").Key("INSTALL_LOCK").MustBool(false)
- if installLock {
+ if HasInstallLock(rootCfg) {
currentUser, match := IsRunUserMatchCurrentUser(RunUser)
if !match {
log.Fatal("Expect user '%s' but current user is: %s", RunUser, currentUser)
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 58fd84308d..c4c9d32e1d 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -296,6 +296,8 @@ invalid_password_algorithm = Invalid password hash algorithm
password_algorithm_helper = Set the password hashing algorithm. Algorithms have differing requirements and strength. The argon2 algorithm is rather secure but uses a lot of memory and may be inappropriate for small systems.
enable_update_checker = Enable Update Checker
enable_update_checker_helper = Checks for new version releases periodically by connecting to gitea.io.
+env_config_keys = Environment Configuration
+env_config_keys_prompt = The following environment variables will also be applied to your configuration file:
[home]
uname_holder = Username or Email Address
diff --git a/routers/install/install.go b/routers/install/install.go
index f121f31376..a2e89d3dac 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -56,6 +56,7 @@ func getSupportedDbTypeNames() (dbTypeNames []map[string]string) {
func Contexter() func(next http.Handler) http.Handler {
rnd := templates.HTMLRenderer()
dbTypeNames := getSupportedDbTypeNames()
+ envConfigKeys := setting.CollectEnvConfigKeys()
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
base, baseCleanUp := context.NewBaseContext(resp, req)
@@ -70,11 +71,13 @@ func Contexter() func(next http.Handler) http.Handler {
ctx.AppendContextValue(context.WebContextKey, ctx)
ctx.Data.MergeFrom(middleware.CommonTemplateContextData())
ctx.Data.MergeFrom(middleware.ContextData{
- "locale": ctx.Locale,
- "Title": ctx.Locale.Tr("install.install"),
- "PageIsInstall": true,
- "DbTypeNames": dbTypeNames,
- "AllLangs": translation.AllLangs(),
+ "locale": ctx.Locale,
+ "Title": ctx.Locale.Tr("install.install"),
+ "PageIsInstall": true,
+ "DbTypeNames": dbTypeNames,
+ "EnvConfigKeys": envConfigKeys,
+ "CustomConfFile": setting.CustomConf,
+ "AllLangs": translation.AllLangs(),
"PasswordHashAlgorithms": hash.RecommendedHashAlgorithms,
})
@@ -218,7 +221,7 @@ func checkDatabase(ctx *context.Context, form *forms.InstallForm) bool {
return false
}
- log.Info("User confirmed reinstallation of Gitea into a pre-existing database")
+ log.Info("User confirmed re-installation of Gitea into a pre-existing database")
}
if hasPostInstallationUser || dbMigrationVersion > 0 {
@@ -502,6 +505,8 @@ func SubmitInstall(ctx *context.Context) {
return
}
+ setting.EnvironmentToConfig(cfg, os.Environ())
+
if err = cfg.SaveTo(setting.CustomConf); err != nil {
ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form)
return
@@ -568,6 +573,7 @@ func SubmitInstall(ctx *context.Context) {
}
}
+ setting.ClearEnvConfigKeys()
log.Info("First-time run install finished!")
InstallDone(ctx)
diff --git a/templates/install.tmpl b/templates/install.tmpl
index 48eabe8e74..b5caab1489 100644
--- a/templates/install.tmpl
+++ b/templates/install.tmpl
@@ -1,6 +1,6 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content install">
- <div class="ui middle very relaxed page grid">
+ <div class="ui grid install-config-container">
<div class="sixteen wide center aligned centered column">
<h3 class="ui top attached header">
{{.locale.Tr "install.title"}}
@@ -149,7 +149,7 @@
</div>
<div class="inline field">
<div class="ui checkbox">
- <label for="enable_update_checker">{{.locale.Tr "install.enable_update_checker"}}</label>
+ <label>{{.locale.Tr "install.enable_update_checker"}}</label>
<input name="enable_update_checker" type="checkbox">
</div>
<span class="help">{{.locale.Tr "install.enable_update_checker_helper"}}</span>
@@ -160,7 +160,7 @@
<!-- Email -->
<details class="optional field">
- <summary class="title gt-py-3{{if .Err_SMTP}} text red{{end}}">
+ <summary class="right-content gt-py-3{{if .Err_SMTP}} text red{{end}}">
{{.locale.Tr "install.email_title"}}
</summary>
<div class="inline field">
@@ -200,7 +200,7 @@
<!-- Server and other services -->
<details class="optional field">
- <summary class="title gt-py-3{{if .Err_Services}} text red{{end}}">
+ <summary class="right-content gt-py-3{{if .Err_Services}} text red{{end}}">
{{.locale.Tr "install.server_service_title"}}
</summary>
<div class="inline field">
@@ -298,7 +298,7 @@
<!-- Admin -->
<details class="optional field">
- <summary class="title gt-py-3{{if .Err_Admin}} text red{{end}}">
+ <summary class="right-content gt-py-3{{if .Err_Admin}} text red{{end}}">
{{.locale.Tr "install.admin_title"}}
</summary>
<p class="center">{{.locale.Tr "install.admin_setting_desc"}}</p>
@@ -320,10 +320,27 @@
</div>
</details>
+ {{if .EnvConfigKeys}}
+ <!-- Environment Config -->
+ <h4 class="ui dividing header">{{.locale.Tr "install.env_config_keys"}}</h4>
+ <div class="inline field">
+ <div class="right-content">
+ {{.locale.Tr "install.env_config_keys_prompt"}}
+ </div>
+ <div class="right-content gt-mt-3">
+ {{range .EnvConfigKeys}}<span class="ui label">{{.}}</span>{{end}}
+ </div>
+ </div>
+ {{end}}
+
<div class="divider"></div>
<div class="inline field">
- <label></label>
- <button class="ui primary button">{{.locale.Tr "install.install_btn_confirm"}}</button>
+ <div class="right-content">
+ These configuration options will be written into: {{.CustomConfFile}}
+ </div>
+ <div class="right-content gt-mt-3">
+ <button class="ui primary button">{{.locale.Tr "install.install_btn_confirm"}}</button>
+ </div>
</div>
</form>
</div>
diff --git a/web_src/css/install.css b/web_src/css/install.css
index a65a213fd5..4ac294e902 100644
--- a/web_src/css/install.css
+++ b/web_src/css/install.css
@@ -1,5 +1,6 @@
-.page-content.install {
- padding-top: 45px;
+.page-content.install .install-config-container {
+ max-width: 900px;
+ margin: auto;
}
.page-content.install form.ui.form .inline.field > label {
@@ -9,26 +10,20 @@
margin-right: 0;
}
-.page-content.install form.ui.form .inline.field > .ui.checkbox:first-child {
+.page-content.install .ui.form .field > .help,
+.page-content.install .ui.form .field > .ui.checkbox:first-child,
+.page-content.install .ui.form .field > .right-content {
margin-left: 30%;
padding-left: 5px;
-}
-
-.page-content.install form.ui.form .inline.field > .ui.checkbox:first-child label {
width: auto;
}
-.page-content.install form.ui.form .title {
- margin-left: 30%;
- padding-left: 5px;
-}
-
.page-content.install form.ui.form input {
width: 60%;
}
.page-content.install form.ui.form details.optional.field[open] {
- border-bottom: 1px solid var(--color-secondary);
+ border-bottom: 1px dashed var(--color-secondary);
padding-bottom: 10px;
}
@@ -44,12 +39,6 @@
text-align: left;
}
-.page-content.install form.ui.form .field .help {
- margin-left: 30%;
- padding-left: 5px;
- width: 60%;
-}
-
.page-content.install .ui .reinstall-message {
width: 70%;
margin: 20px auto;