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

> Configure Gitea settings using app.ini, environment variables, and CLI commands. Master Gitea configuration for optimal performance and control.

- Repository: [Gitea/gitea](https://github.com/go-gitea/gitea)
- Tags: how-to-guide
- Published: 2026-03-07

---

**Gitea settings are controlled through the [`app.ini`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/modules/setting/setting.go)** (lines 89-95). This function creates a `ConfigProvider` (implemented in **[`modules/setting/config_provider.go`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/app.ini) in the path specified by `--config`, then `$GITEA_CUSTOM/conf/app.ini`, and finally falls back to [`custom/conf/app.ini`](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.ini).
2. **Common Settings Loading** – `LoadCommonSettings` 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`](https://github.com/go-gitea/gitea/blob/main/cmd/web.go) and [`cmd/serv.go`](https://github.com/go-gitea/gitea/blob/main/cmd/serv.go) apply final modifications to global variables with "last-wins" precedence.

## Configuring the app.ini File

The [`app.ini`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.ini)

Reference the full example at **[`custom/conf/app.example.ini`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/modules/setting/server.go)** (lines 84-90), this section controls network accessibility and URL generation:

```ini
[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 = admin@example.com

```

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`](https://github.com/go-gitea/gitea/blob/main/modules/setting/database.go)**, supporting SQLite, MySQL, PostgreSQL, and MSSQL:

```ini
[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`](https://github.com/go-gitea/gitea/blob/main/modules/setting/security.go)**:

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

```

**Repository Storage** (`[repository]`)

Configured via **[`modules/setting/repository.go`](https://github.com/go-gitea/gitea/blob/main/modules/setting/repository.go)** using the `ConfigProvider.Section("repository")` API:

```ini
[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:

```bash

# 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`](https://github.com/go-gitea/gitea/blob/main/cmd/web.go)** and **[`cmd/serv.go`](https://github.com/go-gitea/gitea/blob/main/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:

```go
// 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`](https://github.com/go-gitea/gitea/blob/main/modules/setting/setting.go)** and sub-modules like [`server.go`](https://github.com/go-gitea/gitea/blob/main/server.go) and [`database.go`](https://github.com/go-gitea/gitea/blob/main/database.go), providing strongly-typed access to variables such as `setting.HTTPPort`, `setting.Domain`, or `setting.DisableSSH`.

## Summary

- **Primary configuration** happens in [`app.ini`](https://github.com/go-gitea/gitea/blob/main/app.ini), loaded by `InitCfgProvider` in [`modules/setting/setting.go`](https://github.com/go-gitea/gitea/blob/main/modules/setting/setting.go)
- **Environment variables** using the `GITEA__SECTION__KEY` pattern override file settings for Docker and Kubernetes deployments
- **Command-line flags** in [`cmd/web.go`](https://github.com/go-gitea/gitea/blob/main/cmd/web.go) provide final override capabilities at startup
- **Key source files** include [`modules/setting/server.go`](https://github.com/go-gitea/gitea/blob/main/modules/setting/server.go) (networking), [`modules/setting/database.go`](https://github.com/go-gitea/gitea/blob/main/modules/setting/database.go) (storage), and [`modules/setting/security.go`](https://github.com/go-gitea/gitea/blob/main/modules/setting/security.go) (policies)
- **Runtime access** requires importing `code.gitea.io/gitea/modules/setting` and reading exported variables like `setting.AppURL`

## Frequently Asked Questions

### Where is the Gitea configuration file located?

Gitea searches for [`app.ini`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.ini) in the installation directory. The `InitCfgProvider` function in [`modules/setting/setting.go`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/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`](https://github.com/go-gitea/gitea/blob/main/modules/setting/server.go) (lines 86-106), `ROOT_URL` generates absolute links and webhooks, whereas `DOMAIN` determines SSH URL hostnames and cookie scope.