Skip to content

Commit b4460cf

Browse files
authored
Make "install page" respect environment config (#25648) (#25799)
Backport #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. The only conflict during backport is "ui divider" in templates/install.tmpl
1 parent a1bc2aa commit b4460cf

File tree

13 files changed

+88
-71
lines changed

13 files changed

+88
-71
lines changed

contrib/environment-to-ini/environment-to-ini.go

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ package main
55

66
import (
77
"os"
8-
"strings"
98

109
"code.gitea.io/gitea/modules/log"
1110
"code.gitea.io/gitea/modules/setting"
1211

1312
"github.com/urfave/cli"
1413
)
1514

16-
// EnvironmentPrefix environment variables prefixed with this represent ini values to write
17-
const EnvironmentPrefix = "GITEA"
18-
1915
func main() {
2016
app := cli.NewApp()
2117
app.Name = "environment-to-ini"
@@ -70,15 +66,6 @@ func main() {
7066
Value: "",
7167
Usage: "Destination file to write to",
7268
},
73-
cli.BoolFlag{
74-
Name: "clear",
75-
Usage: "Clears the matched variables from the environment",
76-
},
77-
cli.StringFlag{
78-
Name: "prefix, p",
79-
Value: EnvironmentPrefix,
80-
Usage: "Environment prefix to look for - will be suffixed by __ (2 underscores)",
81-
},
8269
}
8370
app.Action = runEnvironmentToIni
8471
err := app.Run(os.Args)
@@ -99,9 +86,7 @@ func runEnvironmentToIni(c *cli.Context) error {
9986
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
10087
}
10188

102-
prefixGitea := c.String("prefix") + "__"
103-
suffixFile := "__FILE"
104-
changed := setting.EnvironmentToConfig(cfg, prefixGitea, suffixFile, os.Environ())
89+
changed := setting.EnvironmentToConfig(cfg, os.Environ())
10590

10691
// try to save the config file
10792
destination := c.String("out")
@@ -116,19 +101,5 @@ func runEnvironmentToIni(c *cli.Context) error {
116101
}
117102
}
118103

119-
// clear Gitea's specific environment variables if requested
120-
if c.Bool("clear") {
121-
for _, kv := range os.Environ() {
122-
idx := strings.IndexByte(kv, '=')
123-
if idx < 0 {
124-
continue
125-
}
126-
eKey := kv[:idx]
127-
if strings.HasPrefix(eKey, prefixGitea) {
128-
_ = os.Unsetenv(eKey)
129-
}
130-
}
131-
}
132-
133104
return nil
134105
}

docs/content/doc/installation/with-docker-rootless.en-us.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ docker-compose up -d
288288

289289
In addition to the environment variables above, any settings in `app.ini` can be set
290290
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
291-
These settings are applied each time the docker container starts.
291+
These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
292292
Full information [here](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini).
293293

294294
These environment variables can be passed to the docker container in `docker-compose.yml`.

docs/content/doc/installation/with-docker.en-us.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ docker-compose up -d
289289

290290
In addition to the environment variables above, any settings in `app.ini` can be set
291291
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
292-
These settings are applied each time the docker container starts.
292+
These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
293293
Full information [here](https://github.com/go-gitea/gitea/tree/master/contrib/environment-to-ini).
294294

295295
These environment variables can be passed to the docker container in `docker-compose.yml`.

modules/assetfs/layered.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ func (l *LayeredFS) WatchLocalChanges(ctx context.Context, callback func()) {
215215
log.Error("Unable to list directories for asset local file-system %q: %v", layer.localPath, err)
216216
continue
217217
}
218+
layerDirs = append(layerDirs, ".")
218219
for _, dir := range layerDirs {
219220
if err = watcher.Add(util.FilePathJoinAbs(layer.localPath, dir)); err != nil {
220221
log.Error("Unable to watch directory %s: %v", dir, err)

modules/setting/config_env.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,31 @@ import (
1212
"code.gitea.io/gitea/modules/log"
1313
)
1414

15+
const (
16+
EnvConfigKeyPrefixGitea = "GITEA__"
17+
EnvConfigKeySuffixFile = "__FILE"
18+
)
19+
1520
const escapeRegexpString = "_0[xX](([0-9a-fA-F][0-9a-fA-F])+)_"
1621

1722
var escapeRegex = regexp.MustCompile(escapeRegexpString)
1823

24+
func CollectEnvConfigKeys() (keys []string) {
25+
for _, env := range os.Environ() {
26+
if strings.HasPrefix(env, EnvConfigKeyPrefixGitea) {
27+
k, _, _ := strings.Cut(env, "=")
28+
keys = append(keys, k)
29+
}
30+
}
31+
return keys
32+
}
33+
34+
func ClearEnvConfigKeys() {
35+
for _, k := range CollectEnvConfigKeys() {
36+
_ = os.Unsetenv(k)
37+
}
38+
}
39+
1940
// decodeEnvSectionKey will decode a portable string encoded Section__Key pair
2041
// Portable strings are considered to be of the form [A-Z0-9_]*
2142
// 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
87108
return ok, section, key, useFileValue
88109
}
89110

90-
func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, envs []string) (changed bool) {
111+
func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) {
91112
for _, kv := range envs {
92113
idx := strings.IndexByte(kv, '=')
93114
if idx < 0 {
@@ -97,7 +118,7 @@ func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, env
97118
// parse the environment variable to config section name and key name
98119
envKey := kv[:idx]
99120
envValue := kv[idx+1:]
100-
ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixGitea, suffixFile, envKey)
121+
ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(EnvConfigKeyPrefixGitea, EnvConfigKeySuffixFile, envKey)
101122
if !ok {
102123
continue
103124
}

modules/setting/config_env_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func TestDecodeEnvironmentKey(t *testing.T) {
7272
func TestEnvironmentToConfig(t *testing.T) {
7373
cfg, _ := NewConfigProviderFromData("")
7474

75-
changed := EnvironmentToConfig(cfg, "GITEA__", "__FILE", nil)
75+
changed := EnvironmentToConfig(cfg, nil)
7676
assert.False(t, changed)
7777

7878
cfg, err := NewConfigProviderFromData(`
@@ -81,16 +81,16 @@ key = old
8181
`)
8282
assert.NoError(t, err)
8383

84-
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
84+
changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key=new"})
8585
assert.True(t, changed)
8686
assert.Equal(t, "new", cfg.Section("sec").Key("key").String())
8787

88-
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
88+
changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key=new"})
8989
assert.False(t, changed)
9090

9191
tmpFile := t.TempDir() + "/the-file"
9292
_ = os.WriteFile(tmpFile, []byte("value-from-file"), 0o644)
93-
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key__FILE=" + tmpFile})
93+
changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
9494
assert.True(t, changed)
9595
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
9696
}

modules/setting/path.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ func InitWorkPathAndCfgProvider(getEnvFn func(name string) string, args ArgWorkP
171171

172172
// only read the config but do not load/init anything more, because the AppWorkPath and CustomPath are not ready
173173
InitCfgProvider(tmpCustomConf.Value)
174+
if HasInstallLock(CfgProvider) {
175+
ClearEnvConfigKeys() // if the instance has been installed, do not pass the environment variables to sub-processes
176+
}
174177
configWorkPath := ConfigSectionKeyString(CfgProvider.Section(""), "WORK_PATH")
175178
if configWorkPath != "" {
176179
if !filepath.IsAbs(configWorkPath) {

modules/setting/security.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func generateSaveInternalToken(rootCfg ConfigProvider) {
102102

103103
func loadSecurityFrom(rootCfg ConfigProvider) {
104104
sec := rootCfg.Section("security")
105-
InstallLock = sec.Key("INSTALL_LOCK").MustBool(false)
105+
InstallLock = HasInstallLock(rootCfg)
106106
LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt(7)
107107
CookieUserName = sec.Key("COOKIE_USERNAME").MustString("gitea_awesome")
108108
SecretKey = loadSecret(sec, "SECRET_KEY_URI", "SECRET_KEY")

modules/setting/setting.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,14 @@ func loadRunModeFrom(rootCfg ConfigProvider) {
183183
}
184184
}
185185

186+
// HasInstallLock checks the install-lock in ConfigProvider directly, because sometimes the config file is not loaded into setting variables yet.
187+
func HasInstallLock(rootCfg ConfigProvider) bool {
188+
return rootCfg.Section("security").Key("INSTALL_LOCK").MustBool(false)
189+
}
190+
186191
func mustCurrentRunUserMatch(rootCfg ConfigProvider) {
187192
// Does not check run user when the "InstallLock" is off.
188-
installLock := rootCfg.Section("security").Key("INSTALL_LOCK").MustBool(false)
189-
if installLock {
193+
if HasInstallLock(rootCfg) {
190194
currentUser, match := IsRunUserMatchCurrentUser(RunUser)
191195
if !match {
192196
log.Fatal("Expect user '%s' but current user is: %s", RunUser, currentUser)

options/locale/locale_en-US.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ invalid_password_algorithm = Invalid password hash algorithm
290290
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.
291291
enable_update_checker = Enable Update Checker
292292
enable_update_checker_helper = Checks for new version releases periodically by connecting to gitea.io.
293+
env_config_keys = Environment Configuration
294+
env_config_keys_prompt = The following environment variables will also be applied to your configuration file:
293295

294296
[home]
295297
uname_holder = Username or Email Address

0 commit comments

Comments
 (0)