How to Configure Gitea Settings: Complete Guide to app.ini, Environment Variables, and CLI

Gitea settings are controlled through the app.ini configuration file, environment variables using the GITEA__SECTION__KEY pattern, and command-line flags, with all values loaded at startup by the setting package in the go-gitea/gitea codebase.

The go-gitea/gitea repository uses a centralized configuration system that maps INI file values into strongly-typed Go variables exported from the setting module. Understanding how to configure Gitea settings properly ensures you can manage everything from network ports and database connections to security policies and repository storage paths.

Understanding the Configuration Loading Architecture

Gitea initializes its configuration early in the startup process through the InitCfgProvider function in modules/setting/setting.go (lines 89-95). This function creates a ConfigProvider (implemented in modules/setting/config_provider.go) that parses the INI format and disables write-back capabilities to keep configurations immutable at runtime.

The loading sequence follows strict dependency order:

  1. File Discovery – Gitea searches for app.ini in the path specified by --config, then $GITEA_CUSTOM/conf/app.ini, and finally falls back to custom/conf/app.ini.
  2. Common Settings LoadingLoadCommonSettings invokes loadCommonSettingsFrom, which calls section-specific loader functions like loadServerFrom, preserving order because many settings depend on previously loaded values.
  3. Environment Injection – Variables matching the GITEA__SECTION__KEY pattern override file values automatically via the configuration parser.
  4. CLI Overrides – Command-line flags processed in cmd/web.go and cmd/serv.go apply final modifications to global variables with "last-wins" precedence.

Configuring the app.ini File

The app.ini file remains the primary method to configure Gitea settings, organized into sections that map to specific loader functions in the codebase.

Configuration File Locations

Gitea looks for app.ini in the following precedence:

  • Flag-specified path: Use gitea web --config /path/to/app.ini
  • Custom environment path: $GITEA_CUSTOM/conf/app.ini
  • Default location: custom/conf/app.ini

Reference the full example at custom/conf/app.example.ini in the repository for all available options.

Core Configuration Sections

Server Settings ([server])

Parsed by loadServerFrom in modules/setting/server.go (lines 84-90), this section controls network accessibility and URL generation:

[server]

# The public URL of the instance (must end with a slash)

ROOT_URL = https://git.example.com/
DOMAIN   = git.example.com
HTTP_PORT = 3000
PROTOCOL = https

# Enable automatic HTTPS via ACME (Let's Encrypt)

ENABLE_ACME = true
ACME_EMAIL = [email protected]

The loadServerFrom function (lines 86-106) performs URL parsing and port normalization, deriving values like AbsoluteAssetURL and ManifestData from ROOT_URL.

Database Connection ([database])

Handled in modules/setting/database.go, supporting SQLite, MySQL, PostgreSQL, and MSSQL:

[database]
DB_TYPE  = sqlite3
PATH     = data/gitea.db

# For MySQL/PostgreSQL set HOST, USER, PASSWD, NAME, etc.

Security Policies ([security])

Defined in modules/setting/security.go:

[security]
INSTALL_LOCK = true
SECRET_KEY   = super-secret-random-string

Repository Storage ([repository])

Configured via modules/setting/repository.go using the ConfigProvider.Section("repository") API:

[repository]
ROOT = /var/lib/gitea/git
DEFAULT_PUSH_INTERVAL = 10

Environment Variable Overrides

For containerized deployments, configure Gitea settings using the GITEA__SECTION__KEY pattern, where double underscores separate the section name from the key:


# Change the HTTP port without editing the file

export GITEA__SERVER__HTTP_PORT=8080

# Set a custom secret key

export GITEA__SECURITY__SECRET_KEY=$(openssl rand -hex 32)

These variables are applied automatically when the ConfigProvider initializes, enabling container orchestration to inject configuration without mounting volumes.

Command-Line Configuration Flags

Gitea supports CLI flags that override file and environment settings, processed in cmd/web.go and cmd/serv.go:

  • --config – Specify an alternate configuration file path
  • --work-path – Set the working directory for repositories and data
  • --port or -p – Override the HTTP port defined in [server]
  • --admin-user – Define initial administrator credentials during installation

Accessing Settings in Application Code

When extending Gitea, access configured values through the setting package without re-parsing files:

// Example: reading the server URL from any part of the application
import "code.gitea.io/gitea/modules/setting"

func printBaseURL() {
    fmt.Println("Gitea is reachable at:", setting.AppURL)
}

All loaded values are exported from modules/setting/setting.go and sub-modules like server.go and database.go, providing strongly-typed access to variables such as setting.HTTPPort, setting.Domain, or setting.DisableSSH.

Summary

Frequently Asked Questions

Where is the Gitea configuration file located?

Gitea searches for app.ini in three locations: first checking the path provided by the --config flag, then falling back to $GITEA_CUSTOM/conf/app.ini, and finally using custom/conf/app.ini in the installation directory. The InitCfgProvider function in modules/setting/setting.go implements this discovery logic at lines 89-95.

How do I change Gitea settings without restarting?

Most Gitea settings require a process restart to take effect because the ConfigProvider loads values once at startup and disables write-back to maintain immutability. While some administrative settings can be modified through the web interface, core configurations in app.ini or environment variables necessitate restarting the Gitea process or container to reload InitCfgProvider.

Can I use environment variables for all Gitea settings?

Yes. Gitea supports the GITEA__SECTION__KEY pattern for every configuration option available in app.ini. For example, GITEA__SERVER__ROOT_URL maps to the ROOT_URL key in the [server] section. This pattern is processed automatically by the configuration parser during the initialization sequence.

What is the difference between ROOT_URL and DOMAIN in Gitea configuration?

ROOT_URL specifies the complete public URL including protocol and port (e.g., https://git.example.com/), while DOMAIN sets the bare hostname (e.g., git.example.com). According to the loadServerFrom implementation in modules/setting/server.go (lines 86-106), ROOT_URL generates absolute links and webhooks, whereas DOMAIN determines SSH URL hostnames and cookie scope.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →