# Gitea User Guide

## 1. Quick Start

Gitea is a painless, self-hosted Git service written in Go. It provides repository hosting, issue tracking, pull requests, code review, CI/CD (Gitea Actions), a built-in package registry, wiki, and project boards — all in a single binary with minimal resource requirements.

**Key features:**

- Git repository hosting with web-based management
- Issues, pull requests, and code review workflows
- Gitea Actions (GitHub Actions-compatible CI/CD)
- Built-in package registry supporting 20+ formats
- Wiki, project boards, and release management
- Migration from GitHub, GitLab, Bitbucket, Gogs, and more
- LDAP, OAuth2, SMTP, and SAML authentication
- Webhook integrations (Slack, Discord, Telegram, Matrix, Microsoft Teams, and others)

**Prerequisites:** Git 2.0+, a supported database (SQLite for quick start, PostgreSQL/MySQL/MSSQL for production).

**Fastest way to start (Docker):**

```bash
docker run -d --name gitea -p 3000:3000 -p 2222:22 gitea/gitea:latest
```

```text
...
Status: Downloaded newer image for gitea/gitea:latest
<container_id>
```

Open `http://localhost:3000` in your browser to complete the initial setup wizard.

> [!TIP]
> For a quick evaluation without Docker, download the pre-built binary for your platform from the [Gitea downloads page](https://dl.gitea.com/gitea/) and run `./gitea web`. Gitea uses SQLite by default, so no external database is needed for testing.

**What to try next:**

- Create your first repository (see Core Usage below)
- Configure authentication (see Configuration)
- Set up Gitea Actions for CI/CD (see Common Tasks)
- See the Admin Guide for full configuration reference and deployment options

## 2. Installation

### System Requirements

| Component | Minimum | Recommended |
|---|---|---|
| CPU | 1 core | 2+ cores |
| RAM | 512 MB | 1 GB+ |
| Disk | 1 GB | Depends on repository size |
| Git | 2.0+ | Latest stable |
| Database | SQLite 3 | PostgreSQL 12+ / MySQL 8.0+ / MSSQL 2012+ |
| OS | Linux, macOS, Windows, FreeBSD | Linux (amd64) |

### Installation Methods

=== "Docker"
    ```bash
    # Standard (root-based)
    docker pull gitea/gitea:latest
    docker run -d --name gitea \
      -p 3000:3000 -p 2222:22 \
      -v /opt/gitea/data:/data \
      -v /etc/timezone:/etc/timezone:ro \
      -v /etc/localtime:/etc/localtime:ro \
      gitea/gitea:latest
    ```

=== "Docker (Rootless)"
    ```bash
    docker pull gitea/gitea:latest-rootless
    docker run -d --name gitea \
      -p 3000:3000 -p 2222:2222 \
      -v /opt/gitea/data:/var/lib/gitea \
      -v /opt/gitea/config:/etc/gitea \
      gitea/gitea:latest-rootless
    ```

=== "Binary"
    ```bash
    # Download for your platform (example: Linux amd64)
    wget -O gitea https://dl.gitea.com/gitea/latest/gitea-latest-linux-amd64
    chmod +x gitea
    ./gitea web
    ```

=== "Snap"
    ```bash
    sudo snap install gitea
    ```

=== "Source"
    ```bash
    git clone https://github.com/go-gitea/gitea.git
    cd gitea
    TAGS="bindata sqlite sqlite_unlock_notify" make build
    ./gitea web
    ```

> [!IMPORTANT]
> When building from source, the `bindata` build tag embeds web assets into the binary. Without it, Gitea expects assets in the working directory. For production deployments, always build with `bindata`.

### Post-Install Verification

```bash
gitea --version
```

```text
Gitea version 1.26.0 built with go1.26.2 : bindata, sqlite, sqlite_unlock_notify
```

Then open `http://localhost:3000` to access the web-based initial configuration wizard. The wizard will guide you through database setup, admin account creation, and basic settings.

### Install Troubleshooting

### Error: `installed git version is not supported, Gitea requires git version >= 2.0`

**Cause:** Your system Git is too old.

**Solution:**
1. Update Git to version 2.0 or later
2. Verify with `git --version`

**Prevention:** Use a package manager that provides current Git versions.

### Error: `unable to prepare git home directory`

**Cause:** Gitea cannot write to the Git home directory.

**Solution:**
1. Ensure the Gitea process user has write access to the configured home directory
2. Check directory permissions: `ls -la /path/to/gitea-home`

**Prevention:** Run Gitea under a dedicated service account with appropriate directory permissions.

### Error: `LFS server support requires Git >= 2.1.2`

**Cause:** Git LFS features require a newer Git version.

**Solution:**
1. Upgrade Git to 2.1.2 or later
2. If you do not need LFS, disable it in configuration

**Prevention:** Keep Git updated to the latest stable release.

### Error: Port 3000 already in use

**Cause:** Another service is using the default Gitea port.

**Solution:**
1. Stop the conflicting service, or
2. Change Gitea's port: set `HTTP_PORT` in `[server]` section of `app.ini`

**Prevention:** Choose a unique port during initial setup.

### Error: Database connection failed

**Cause:** Database is not running, credentials are wrong, or network is unreachable.

**Solution:**
1. Verify the database service is running
2. Check the connection string in `[database]` section of `app.ini`
3. Test connectivity manually (e.g., `psql` for PostgreSQL)

**Prevention:** Verify database access before starting Gitea.

## 3. Configuration

Gitea uses an INI-format configuration file located at `{WorkPath}/custom/conf/app.ini`. On first run, the web installer creates this file. You can also override settings via environment variables using the prefix `GITEA__SECTION__KEY`.

### Essential Settings

```ini
[server]
HTTP_PORT       = 3000
DOMAIN          = git.example.com
ROOT_URL        = https://git.example.com/
SSH_DOMAIN      = git.example.com

[database]
DB_TYPE  = postgres
HOST     = 127.0.0.1:5432
NAME     = gitea
USER     = gitea
PASSWD   = your_password

[repository]
ROOT = /data/gitea/repositories
```

> [!NOTE]
> `ROOT_URL` must match how users access Gitea externally. If behind a reverse proxy with HTTPS, set `ROOT_URL = https://git.example.com/`.

### Common Configuration Combinations

| Goal | Settings |
|---|---|
| HTTPS via reverse proxy | `[server] PROTOCOL = http`, configure reverse proxy for TLS |
| Built-in HTTPS | `[server] PROTOCOL = https`, `CERT_FILE`, `KEY_FILE` |
| Change SSH port | `[server] SSH_PORT = 2222` |
| Disable registration | `[service] DISABLE_REGISTRATION = true` |
| Enable Gitea Actions | `[actions] ENABLED = true` (enabled by default) |
| Use S3 for storage | `[storage] STORAGE_TYPE = minio` with endpoint/bucket/keys |

### Environment Variable Overrides

Any `app.ini` setting can be overridden via environment variables:

```bash
# Pattern: GITEA__SECTION__KEY=value
GITEA__database__DB_TYPE=postgres
GITEA__server__HTTP_PORT=8080
GITEA__service__DISABLE_REGISTRATION=true
```

> [!TIP]
> Environment variable overrides are useful for Docker deployments and CI environments where you want to inject configuration without modifying the config file. Special characters in section or key names can be hex-encoded: `_0X2E_` for `.`, `_0X2D_` for `-`.

For the complete configuration reference with every section, key, and default value, see the Admin Guide.

## 4. Core Usage

### Creating and Managing Repositories

**Create a new repository:**

1. Click **+** in the navigation bar and select **New Repository**
2. Fill in the repository name, description, and visibility (public/private)
3. Optionally initialize with a README, .gitignore, and license
4. Click **Create Repository**

**Clone a repository:**

```bash
# HTTPS
git clone https://git.example.com/username/repo.git

# SSH
git clone [email removed]:username/repo.git
```

```text
Cloning into 'repo'...
remote: Enumerating objects: 42, done.
```

**Fork a repository:** Click the **Fork** button on any repository page to create your own copy.

**Mirror a repository:** When creating a repository, select **New Migration** to mirror from an external source. Gitea supports push and pull mirrors that sync automatically.

### Issues and Issue Tracking

- Create issues from the repository **Issues** tab
- Use labels, milestones, and assignees to organize work
- Reference issues in commits with `#123` syntax (auto-linked)
- Close issues automatically with commit messages: `Closes #123`, `Fixes #456`
- Use issue templates (placed in `.gitea/issue_template/` or `.github/issue_template/`) for structured reporting
- Track time on issues with the built-in time tracker

> [!NOTE]
> Gitea supports Markdown in all text fields, including GitHub-flavored Markdown extensions like task lists (`- [x] Done`), tables, and fenced code blocks with syntax highlighting.

### Pull Requests and Code Review

1. Push a feature branch to your fork or the same repository
2. Click **New Pull Request** and select the source and target branches
3. Add a title, description, labels, and reviewers
4. Reviewers can approve, request changes, or leave comments
5. Use inline code comments for line-specific feedback
6. Merge when reviews pass (merge, rebase, squash, or fast-forward strategies available)

**Auto-merge:** Enable auto-merge on a pull request so it merges automatically once all required reviews and status checks pass.

> [!WARNING]
> Branch protection rules must be configured by repository admins to enforce review requirements. Without protection rules, any user with write access can push directly to the target branch.

### Gitea Actions (CI/CD)

Gitea Actions is a built-in CI/CD system compatible with GitHub Actions workflow syntax. Workflows are defined in `.gitea/workflows/` or `.github/workflows/` directories.

**Example workflow (`.gitea/workflows/ci.yml`):**

```yaml
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.22'
      - run: go test ./...
```

**Register a runner:**

```bash
# Generate a runner registration token
gitea actions generate-runner-token --scope owner/repo

# Or generate a global token
gitea actions generate-runner-token
```

```text
<runner_registration_token>
```

> [!TIP]
> The `GITEA_RUNNER_REGISTRATION_TOKEN` environment variable can also be set to auto-register runners at startup. By default, Gitea resolves action references from GitHub (`DEFAULT_ACTIONS_URL = github`). Set `DEFAULT_ACTIONS_URL = self` in `[actions]` to use your own Gitea instance as the action source.

**Skip workflows:** Include any of these strings in a commit message to skip workflow execution: `[skip ci]`, `[ci skip]`, `[no ci]`, `[skip actions]`, `[actions skip]`.

### Wiki

Each repository can have an associated wiki. Access it from the **Wiki** tab.

- Create and edit pages using Markdown
- Wiki content is stored as a separate Git repository (`repo.wiki.git`)
- Clone and edit wikis locally with Git

### Projects (Kanban Boards)

Organize work with project boards at the repository or organization level:

1. Go to **Projects** and create a new project
2. Add columns (e.g., To Do, In Progress, Done)
3. Link issues and pull requests to the project
4. Drag cards between columns to update status

### Package Registry

Gitea includes a built-in package registry supporting many formats:

| Format | Path |
|---|---|
| Generic | `/api/packages/{owner}/generic/` |
| npm | `/api/packages/{owner}/npm/` |
| PyPI | `/api/packages/{owner}/pypi/` |
| Maven | `/api/packages/{owner}/maven/` |
| NuGet | `/api/packages/{owner}/nuget/` |
| Cargo | `/api/packages/{owner}/cargo/` |
| Container (OCI) | `/v2/{owner}/` |
| Composer | `/api/packages/{owner}/composer/` |
| Conan | `/api/packages/{owner}/conan/` |
| Conda | `/api/packages/{owner}/conda/` |
| Chef | `/api/packages/{owner}/chef/` |
| Helm | `/api/packages/{owner}/helm/` |
| Vagrant | `/api/packages/{owner}/vagrant/` |
| RubyGems | `/api/packages/{owner}/rubygems/` |
| Debian | `/api/packages/{owner}/debian/` |
| RPM | `/api/packages/{owner}/rpm/` |
| Alpine | `/api/packages/{owner}/alpine/` |
| Swift | `/api/packages/{owner}/swift/` |
| Go | `/api/packages/{owner}/go/` |
| CRAN | `/api/packages/{owner}/cran/` |
| Pub | `/api/packages/{owner}/pub/` |
| Terraform | `/api/packages/{owner}/terraform/` |

> [!NOTE]
> Package registry authentication uses the same API tokens as the REST API. Generate a personal access token from **User Settings > Applications**.

### Releases

Create releases from the repository **Releases** tab:

1. Click **New Release**
2. Choose or create a tag
3. Add a title, description, and optional file attachments
4. Mark as pre-release if applicable
5. Publish

Releases automatically generate source code archives (`.tar.gz` and `.zip`).

### Repository Migration

Migrate repositories from other platforms:

1. Click **+** > **New Migration**
2. Select the source platform (GitHub, GitLab, Gitea, Gogs, Bitbucket, OneDev, CodeCommit, Codebase)
3. Enter the clone URL and authentication credentials
4. Select what to migrate: issues, pull requests, labels, milestones, releases, wiki
5. Click **Migrate Repository**

### Organizations and Teams

- Create organizations to group repositories and manage team access
- Teams have configurable permissions per repository or across all organization repositories
- Invite members to organizations and assign them to teams

### Webhooks

Configure webhooks from repository, organization, or system settings:

| Service | Description |
|---|---|
| Gitea | Generic Gitea webhook |
| Gogs | Gogs-compatible webhook |
| Slack | Slack channel notifications |
| Discord | Discord channel notifications |
| Telegram | Telegram bot notifications |
| Microsoft Teams | Teams channel notifications |
| Matrix | Matrix room notifications |
| Feishu/Lark | Feishu notifications |
| DingTalk | DingTalk notifications |
| WeCom/WeChatWork | WeCom notifications |
| Packagist | Packagist update trigger |

## 5. Common Tasks

### Task: Set Up a Complete CI/CD Pipeline with Gitea Actions

**Goal:** Automatically test and build on every push and pull request.

**Prerequisites:** A running Gitea instance with Actions enabled; at least one registered runner.

**Steps:**

1. Create `.gitea/workflows/ci.yml` in your repository:

```yaml
name: CI Pipeline
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build
        run: make build
      - name: Test
        run: make test
```

2. Push the workflow file to your repository
3. Verify the workflow runs in the **Actions** tab

**If it fails:** Check that a runner is registered and online. Verify the runner can pull the action images.

### Task: Migrate a Repository from GitHub

**Goal:** Move a repository including issues, PRs, and wiki from GitHub.

**Prerequisites:** A GitHub personal access token with `repo` scope.

**Steps:**

1. In Gitea, click **+** > **New Migration**
2. Select **GitHub** as the source
3. Enter the repository URL (e.g., `https://github.com/owner/repo`)
4. Enter your GitHub access token
5. Check the items to migrate (issues, labels, milestones, pull requests, releases, wiki)
6. Click **Migrate Repository**

**Verify:** Check that issues, PRs, and wiki content appear correctly.

**If it fails:** Ensure the token has sufficient permissions. For private repositories, the token needs `repo` scope.

### Task: Configure LDAP Authentication

**Goal:** Allow users to sign in with their LDAP/Active Directory credentials.

**Prerequisites:** Access to the Gitea admin panel and LDAP server details.

**Steps via CLI:**

```bash
gitea admin auth add-ldap \
  --name "Corporate LDAP" \
  --security-protocol ldaps \
  --host ldap.example.com \
  --port 636 \
  --user-search-base "ou=Users,dc=example,dc=com" \
  --user-filter "(&(objectClass=person)(uid=%[1]s))" \
  --email-attribute mail
```

**Steps via Web UI:**

1. Go to **Site Administration** > **Authentication Sources**
2. Click **Add Authentication Source**
3. Select **LDAP (via BindDN)** or **LDAP (Simple Auth)**
4. Fill in the connection details
5. Click **Add Authentication Source**

**Verify:** Log out and sign in with an LDAP user account.

### Task: Set Up Email Notifications

**Goal:** Enable email delivery for repository events.

**Steps:**

1. Configure the mailer in `app.ini`:

```ini
[mailer]
ENABLED        = true
SMTP_ADDR      = smtp.example.com
SMTP_PORT      = 587
FROM           = [email removed]
USER           = [email removed]
PASSWD         = your_smtp_password
```

2. Restart Gitea
3. Users can configure their notification preferences in **User Settings** > **Notifications**

**Verify:** Create a test issue and confirm the assignee receives an email.

### Task: Push a Container Image to the Package Registry

**Goal:** Push a Docker/OCI container image to Gitea's built-in registry.

**Steps:**

1. Log in to the registry:

```bash
docker login git.example.com
```

2. Tag and push:

```bash
docker tag myimage:latest git.example.com/username/myimage:latest
docker push git.example.com/username/myimage:latest
```

```text
The push refers to repository [git.example.com/username/myimage]
latest: digest: sha256:abc123... size: 1234
```

**Verify:** Check the **Packages** tab in your user profile or organization.

### Task: Create a Repository Mirror

**Goal:** Keep a read-only mirror of an external repository synchronized.

**Steps:**

1. Click **+** > **New Migration**
2. Enter the source repository URL
3. Check **This repository will be a mirror**
4. Set the mirror interval (default: 8 hours)
5. Click **Migrate Repository**

**Verify:** Check the repository page — it should show a "Mirror" badge.

### Task: Set Up SSH Key Authentication

**Goal:** Push and pull via SSH without entering a password each time.

**Steps:**

1. Generate an SSH key if you don't have one:

```bash
ssh-keygen -t ed25519 -C "[email removed]"
```

2. Copy the public key:

```bash
cat ~/.ssh/id_ed25519.pub
```

3. In Gitea, go to **User Settings** > **SSH / GPG Keys**
4. Click **Add Key**, paste the public key, and save
5. Clone using the SSH URL:

```bash
git clone [email removed]:username/repo.git
```

### Task: Protect a Branch

**Goal:** Prevent direct pushes to the main branch and require pull request reviews.

**Steps:**

1. Go to repository **Settings** > **Branches**
2. Click **Add New Rule**
3. Set the branch name pattern (e.g., `main`)
4. Enable desired protections:
   - Require pull request reviews
   - Require status checks to pass
   - Block force pushes
   - Restrict who can push
5. Click **Save**

### Task: Run the Gitea Doctor

**Goal:** Diagnose and fix common issues with your Gitea instance.

```bash
gitea doctor check
```

```text
...
[I] Checking database version
[I] Checking if OpenSSH authorized_keys file is up to date
[I] Checking for incorrectly set repository permissions
[I] All checks passed
```

> [!TIP]
> Run `gitea doctor check --fix` to automatically repair issues where possible. Always back up your data first.

### Task: Export/Dump Your Gitea Instance

**Goal:** Create a full backup of your Gitea data.

```bash
gitea dump --type zip
```

```text
2026/05/06 12:00:00 ...creating dump archive gitea-dump-1234567890.zip
2026/05/06 12:00:05 ...done
```

This creates an archive containing the database, repositories, configuration, log files, and custom data.

### Task: Use the REST API

**Goal:** Automate Gitea operations via the API.

**Steps:**

1. Generate a personal access token in **User Settings** > **Applications**
2. Use the token in API requests:

```bash
curl -H "Authorization: token YOUR_TOKEN" \
  https://git.example.com/api/v1/repos/search?q=myproject
```

```json
{
  "ok": true,
  "data": [
    {
      "id": 1,
      "name": "myproject",
      "full_name": "username/myproject"
    }
  ]
}
```

> [!NOTE]
> Full API documentation is available at `https://your-gitea-instance/api/swagger` when Swagger is enabled (enabled by default).

## 6. Troubleshooting

### Diagnostic Decision Tree

```text
Gitea not starting?
├── Check logs: gitea web --log-level debug
├── Config file readable? → Check permissions on app.ini
├── Database reachable? → Test connection string manually
├── Port conflict? → Check with netstat/ss
└── Git version? → gitea doctor check

Web UI issues?
├── Blank page → Check ROOT_URL matches actual access URL
├── 502 error → Reverse proxy misconfiguration
├── Assets missing → Missing bindata tag in build
└── CSP errors → Check Content-Security-Policy headers

Git push/pull failures?
├── SSH: Check SSH keys in Gitea UI
├── HTTPS: Verify credentials / token
├── LFS: Check LFS storage configuration
└── Permissions: Check repository access rights
```

### Error: `Workflow Post-Run Steps Not Executed When Workflow is Cancelled`

**Cause:** When a Gitea Actions workflow is cancelled, post-run cleanup steps may not execute. This is a known issue (go-gitea/gitea#36983).

**Solution:**
1. Ensure critical cleanup is performed by separate jobs that are not dependent on the cancelled job
2. Monitor the issue for upstream fixes

**Prevention:** Design workflows with independent cleanup jobs where possible.

### Error: `CSP bug: Missing 'wasm-unsafe-eval' or 'unsafe-eval'` when opening `.cast` files

**Cause:** The Content Security Policy headers do not include the required directives for rendering asciicast files (go-gitea/gitea#37257).

**Solution:**
1. Add `wasm-unsafe-eval` to your CSP configuration if using a custom CSP
2. Wait for an upstream fix if using default CSP

### Error: `GetCompareInfo, AddRemote: exit status 128 - error: could not lock config file`

**Cause:** Concurrent Git operations can cause lock contention on the config file (go-gitea/gitea#32018).

**Solution:**
1. Retry the operation after a short wait
2. Check for zombie Git processes: `ps aux | grep git`
3. Remove stale lock files if present: `rm -f /path/to/repo/.git/config.lock`

**Prevention:** Ensure adequate system resources. Consider upgrading to a version with improved locking.

### Error: `CODEOWNERS file doesn't support absolute paths`

**Cause:** Gitea's CODEOWNERS implementation requires relative paths (go-gitea/gitea#28107).

**Solution:** Use relative paths in your CODEOWNERS file instead of absolute paths starting with `/`.

### Error: Database migration failure

**Cause:** Interrupted upgrades or incompatible schema changes.

**Solution:**
1. Back up your database before upgrading
2. Run `gitea migrate` to apply pending migrations
3. Check logs for specific migration errors

**Prevention:** Always back up before upgrading Gitea versions.

### Error: SSH connection refused

**Cause:** SSH service is not running or port is blocked.

**Solution:**
1. Verify SSH is enabled in `app.ini`: `[server] START_SSH_SERVER = true`
2. Check the configured SSH port: `[server] SSH_PORT`
3. Verify firewall rules allow the SSH port

### Error: `git archive wrong error if repo missed`

**Cause:** Attempting to create a Git archive for a repository that does not exist produces a confusing error (go-gitea/gitea#23425).

**Solution:** Verify the repository exists and is accessible before attempting archive operations.

> [!WARNING]
> Always back up your Gitea data and database before performing upgrades, migrations, or running `gitea doctor check --fix`. Use `gitea dump` to create a full backup.

### Error: Webhook delivery failures

**Cause:** Target URL is unreachable, returns errors, or times out.

**Solution:**
1. Check the webhook delivery log in repository **Settings** > **Webhooks** > select the webhook > **Recent Deliveries**
2. Verify the target URL is accessible from the Gitea server
3. Check for TLS certificate issues if using HTTPS

### Error: `indexer is not ready`

**Cause:** The search indexer has not finished initializing, or it crashed.

**Solution:**
1. Wait for indexer initialization to complete (check logs)
2. If persistent, rebuild the index: delete the indexer data directory and restart Gitea
3. Check disk space — indexers require significant storage for large instances

**Prevention:** Ensure adequate disk space for the configured indexer type.

> [!CAUTION]
> Deleting the indexer data directory forces a full re-index, which can take a long time on large instances. Schedule this during a maintenance window.

## 7. FAQ

**Q: What databases does Gitea support?**

Gitea supports SQLite, PostgreSQL, MySQL/MariaDB, and Microsoft SQL Server. SQLite is suitable for small deployments and evaluation. PostgreSQL is recommended for production use.

**Q: Can I migrate from Gogs to Gitea?**

Yes. Gitea started as a fork of Gogs, and many Gogs instances can be upgraded directly. Gitea also supports migrating repositories from Gogs via the migration tool (including issues and other metadata).

**Q: Does Gitea support GitHub Actions?**

Yes. Gitea Actions is compatible with the GitHub Actions workflow syntax. You can use `.github/workflows/` or `.gitea/workflows/` directories for your workflow definitions. Most GitHub Actions marketplace actions work with Gitea Actions. You need at least one runner registered to execute workflows.

**Q: How do I reset an admin password?**

Use the CLI:

```bash
gitea admin user change-password --username admin --password new_password
```

**Q: Can Gitea be run behind a reverse proxy?**

Yes. Set `ROOT_URL` to your external URL and configure your reverse proxy (nginx, Caddy, Apache, Traefik) to forward requests. See the Admin Guide for detailed reverse proxy configuration.

**Q: How do I enable dark mode?**

Go to **User Settings** > **Appearance** and select a dark theme. Gitea supports multiple themes including `gitea-dark`.

**Q: What is the maximum file attachment size?**

By default, the maximum attachment size is 100 MB with a limit of 5 files per upload. These can be configured in the `[attachment]` section:

```ini
[attachment]
MAX_SIZE = 100
MAX_FILES = 5
ALLOWED_TYPES = .avif,.csv,.docx,.gif,.gz,.jpeg,.jpg,.json,.log,.md,.mov,.mp4,.pdf,.png,.svg,.tgz,.txt,.webm,.webp,.xls,.xlsx,.zip
```

**Q: Does Gitea support two-factor authentication (2FA)?**

Yes. Users can enable TOTP-based 2FA or WebAuthn/FIDO2 security keys from **User Settings** > **Security**. Admins can require 2FA for all users.

**Q: How do I customize Gitea's appearance?**

Place custom files in the `custom/` directory:

- `custom/templates/` — Override Go templates
- `custom/public/` — Custom static assets (CSS, JS, images)
- `custom/options/label/` — Custom issue label sets
- `custom/options/locale/` — Custom translations

**Q: Can Gitea send email notifications?**

Yes. Configure the `[mailer]` section in `app.ini` with your SMTP server details. Users can then configure their notification preferences per-repository.

**Q: Where are Gitea's logs?**

By default, logs are written to `{WorkPath}/log/`. The log level and output can be configured in the `[log]` section of `app.ini`.

**Q: How do I upgrade Gitea?**

1. Back up your data: `gitea dump`
2. Stop the running instance
3. Replace the binary with the new version
4. Run `gitea migrate` to apply database migrations
5. Start Gitea

**Q: Can I use Gitea as a Go module proxy?**

Yes. Gitea's package registry supports Go modules. Configure your `GOPROXY` to include your Gitea instance.

---

_Generated May 2026 from go-gitea/gitea at 19f0169. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
