aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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.tmpl32
-rw-r--r--web_src/css/install.css25
13 files changed, 88 insertions, 71 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 c39eb7f3eb..872f9b53c5 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 1a9f146e02..8aee3bebbc 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -290,6 +290,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 0ef1cd88b9..24533e1a5c 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>
@@ -161,7 +161,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">
@@ -201,7 +201,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">
@@ -299,7 +299,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>
@@ -321,10 +321,30 @@
</div>
</details>
- <div class="ui divider"></div>
+ {{if .EnvConfigKeys}}
+ <!-- Environment Config -->
+ <h4 class="ui dividing header">{{.locale.Tr "install.env_config_keys"}}</h4>
<div class="inline field">
<label></label>
<button class="ui primary button">{{.locale.Tr "install.install_btn_confirm"}}</button>
+ <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="ui divider"></div>
+
+ <div class="inline field">
+ <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;