October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
VGSources
Blog

How to Self-Host Gitea for Source Code Management on a VPS

Deploy Gitea on your own Linux VPS with Docker Compose or a verified binary. This guide explains persistent storage, database choices, nginx HTTPS, backups, restores, upgrades, and security hardening.
Length11 min Posted Quest giverVGSources Team

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The most repeatable way to self-host Gitea is to run the official Docker image with Docker Compose on a Linux VPS, keep /data on persistent storage outside the container, and place Gitea behind an HTTPS reverse proxy. SQLite is adequate for a small, single-node installation; PostgreSQL or MySQL is the safer choice as users, writes, and integrations grow. A binary installation managed by systemd is a sound alternative when you want the host—not Docker—to own the service lifecycle.

This guide covers provisioning, Docker and binary deployments, nginx TLS termination, database selection, backups, restores, upgrades, and hardening. The examples assume a current Linux VPS, a DNS name such as git.example.com, and administrative access with sudo.

As an Amazon Associate I earn from qualifying purchases.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Plan the VPS before installing Gitea

Gitea stores repositories, attachments, packages, actions data, configuration, logs, and database state. Treat the VPS as a stateful server, not a disposable application host. Choose a Linux distribution you can patch regularly, a public IP or DNS record, and persistent disk capacity that includes room for repository growth and backups.

Minimum prerequisites

  • A current 64-bit Linux VPS with a persistent disk or volume.
  • A DNS record pointing your chosen hostname to the VPS public IP.
  • Firewall access for HTTP/HTTPS and the Git transport you intend to expose. Keep the administrative SSH port restricted to trusted networks where practical.
  • Git version 2.0 or newer on the server; Gitea documents this as a requirement.
  • Either Docker Engine with Docker Compose or a Gitea binary matching the VPS architecture.
  • An off-host location for backups. A second disk on the same VPS does not protect against VPS loss, deletion, or account compromise.

Choose a deployment shape

Decision Small personal or low-write instance Team or growing instance
Runtime Docker Compose with SQLite Docker Compose or a host-managed binary with PostgreSQL or MySQL
Data layout One durable volume plus off-host backups Separate database and repository backup strategy
Network exposure Reverse proxy on the same VPS Reverse proxy, stricter firewall rules, monitoring, and capacity planning
Upgrade method Back up, then pull the pinned image and recreate the container Stage the upgrade and review database compatibility before production

SQLite keeps the first deployment simple because the database is a file in the Gitea data directory. It is most appropriate when one node handles modest write activity. PostgreSQL or MySQL separates database operations from the application and gives a better foundation for a busier team installation. Whichever database you choose, include it in the backup and restore runbook.

#1 Best Overall
Sale
Gaoye Blue Light Blocking Glasses
  • BLUE LIGHT BLOCKING GLASSES: Our blue light glasses for women boast UV400 protection, blocking harmful blue rays from computer screens. With these bluelight glasses women, you can enjoy gaming, reading, or watching TV with no worries of eye strain.
  • EYE RELIEF: Our blue light glasses are engineered to reduce blurry vision or strain caused by prolonged screen time. These womens blue light glasses aid in better sleep by preventing blue light from disrupting your natural sleep cycle, helping you fall asleep faster and enjoy a more restful night's sleep, making them the perfect christmas present.
  • COMFORTABLE: Crafted from durable material, our trendy blue light glasses for woman or blue light glasses men ensure long-lasting comfort. The high-transmittance lenses accessories, gamer gifts for men, help keep your eyes relaxed. Perfect stocking stuffers, gifts for gamers men, christmas gifts for men, halloween costumes.
  • LIGHTWEIGHT: These clear blue light glasses feature a lightweight frame, meaning they’ll stay comfy for long-term wear. Perfect as blue blockers glasses for women or mens blue light glasses, these non-prescription fake glasses for men can be worn throughout the day. The blue light blocking glasses women feature polycarbonate HD lenses, which are anti-reflective and restore true color.
  • WORRY-FREE PURCHASE: If you experience any issues, our support team is ready to assist you quickly. These are the perfect costume glasses for cosplay dressing up.

Deploy Gitea with Docker Compose

Docker is usually the fastest path to a repeatable deployment. The important details are persistent storage, a deliberate image tag, correct ownership, and choosing one image mode. Gitea’s rootful and rootless images are not interchangeable; do not switch between them by changing only the image name while keeping an old data volume.

1. Install Docker and create the project directory

  1. Install Docker Engine and the Compose plugin using your Linux distribution’s supported method.
  2. Create a directory owned by the administrator for the Compose file and a separate persistent directory for Gitea data:
    sudo mkdir -p /opt/gitea /srv/gitea/data
    sudo chown -R root:root /opt/gitea /srv/gitea
  3. Decide whether the data directory is a local disk, attached volume, or another persistent filesystem. Verify that it is mounted at boot before putting repositories into service.

2. Create a minimal Compose definition

The following layout publishes the web service on port 3000 and Git-over-SSH on port 2222 while keeping all application state in a host-mounted directory. The version shown is an example release tag; pin the exact Gitea image version you have approved rather than relying on an unchanging latest tag.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
services:
  gitea:
    image: docker.gitea.com/gitea:28.1.0
    container_name: gitea
    restart: unless-stopped
    ports:
      - "3000:3000"
      - "2222:22"
    volumes:
      - /srv/gitea/data:/data

If nginx will run on the same VPS, bind the web port to loopback instead of making it public:

ports:
  - "127.0.0.1:3000:3000"
  - "2222:22"

Use the published SSH port in clone URLs when it is not port 22. For example, an SSH URL may need the host’s port 2222 configured in an SSH client alias. Do not place the Compose file or database inside the container’s writable layer; recreating the container must not delete application data.

3. Start the container and complete the installer

  1. From /opt/gitea, save the Compose file and start it:
    cd /opt/gitea
    docker compose up -d
  2. Inspect startup output and confirm the container is healthy:
    docker compose ps
    docker compose logs --tail=100 gitea
  3. For a first setup with the port temporarily reachable, open http://server-ip:3000. If the web port is bound to loopback, use an SSH tunnel or configure nginx first.
  4. Select SQLite for a small single-node service, or enter the credentials and hostname for MySQL or PostgreSQL. If you use PostgreSQL, pin its major-version image in Compose. PostgreSQL does not automatically upgrade an existing data directory across major versions; a later major upgrade requires pg_upgrade or dump-and-restore.
  5. Set the site name, administrator account, and public URL. Replace every example credential, generate strong secrets, and finish the installation.
  6. After the installer writes the configuration, enable the installation lock and review the generated settings before opening the service to other users.

4. Correct ownership before troubleshooting permissions

A host-mounted /data directory must be writable by the UID and GID used by the selected image. If logs show permission denied errors, stop the service, identify the image’s service account, and correct ownership on the mounted directory rather than making the entire VPS filesystem world-writable. Do not change from rootful to rootless mode without following the migration procedure for that image family.

Rank #2
Windex Gaming Cleaning Wipes, Pre-Moistened Wipes to Instantly Clean all Gaming Gear and Electronics, Resealable Packaging for a Freshness Lock, 25 count (Pack of 1)
  • WINDEX GAMING WIPES: effortlessly clean all your gaming gear and gaming electronics in one easy step with our new Windex Gaming Wipes
  • AMMONIA FREE: our ammonia-free formula is safe to use on all of your favorite gaming equipment like consoles, headsets, controllers, screens, keyboards, and more
  • PRE-MOISTENED WIPES: each wipe instantly removes dust, dirt, and stubborn smudges and fingerprints leaving a streak-free shine
  • ANTI-STATIC: great for cleaning and wiping down your gaming gear and electronics leaving behind no visible residue
  • COMPACT RESEALABLE PACKAGE: store your pack of Windex Gaming Wipes anywhere in your home for whenever a quick and easy wipedown is needed

Install Gitea as a host-managed binary

A binary installation avoids a container runtime and lets systemd, the host filesystem, and the operating system package process own the service. It requires more deliberate file permissions and upgrade work.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Select and verify the binary

  1. Identify the VPS CPU architecture and download the matching Gitea release binary.
  2. Verify the release using the supplied checksums and signature material. Starting with Gitea v1.27, Gitea signs binaries with Sigstore. A successful cosign verify-blob check reports Verified OK. GPG verification is also documented as an option.
  3. Keep the executable at a stable path such as /usr/local/bin/gitea. During an upgrade, replace that file rather than changing the generic filename referenced by systemd.

2. Create the service account and directories

sudo useradd --system --shell /bin/bash --home /var/lib/gitea --create-home git
sudo mkdir -p /var/lib/gitea/{custom,data,log,repositories}
sudo mkdir -p /etc/gitea
sudo chown -R git:git /var/lib/gitea
sudo chown -R root:git /etc/gitea
sudo chmod 750 /etc/gitea

Use the exact directory arrangement required by your release, but keep repository data under /var/lib/gitea and configuration under /etc/gitea. Restrict /etc/gitea and especially app.ini; it can contain database credentials and signing secrets.

3. Register a systemd service

Create a unit that runs Gitea as the dedicated git user, points to the configuration file, and starts after the network is available. Then reload systemd, enable the unit at boot, and start it. Confirm that the process is listening only on the intended local web and SSH ports before putting nginx in front of it.

sudo systemctl daemon-reload
sudo systemctl enable --now gitea
sudo systemctl status gitea
sudo journalctl -u gitea -n 100 --no-pager

Keep the service account non-root. A dedicated account limits the damage from a compromised application or repository hook.

Put Gitea behind nginx and HTTPS

Terminate TLS at nginx (or another supported reverse proxy) and keep Gitea’s application listener private. In Gitea’s configuration, set the canonical URL exactly:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
Sale
LISEN Cell Phone Stand Phone Holder for Desk, Office Decor Gadgets for Men
  • Ergonomic & Adjustable Design: Fight "text neck" and improve your posture. Designed for comfort, it offers an adjustable height (7.1in-8.5in) (1.4in adjustable range) and angle (5°-85°) Please note: cell phone stand is only 9 inches tall—the length of a standard pencil
  • Without blocking subtitles Perfect for office desk Tiktok Face Time Zoom video—this is the ultimate kitchen desk essential for phones! Perfect viewing experience while reducing neck back strain, A must-have for gamers streamers desk, and anyone who values both style and support!
  • Sleek & Stable Design fits Otterbox Case: Say goodbye to bent cables, tangles, and tip-overs! LISEN’s stylish adjustable desk phone holder features a built-in charging hole and smart cable management, keeping your phone secure and your workspace clutter-free cool gadgets for men
  • ANTI-SLIP DESIGN free hands: The under 10.00 items easy gadgets back and the bottom of this kitchen essentials for women are fully covered by anti-skid silicone, which LISEN stand up desk decor can provide maximum protection device from any scratches and slides
  • Your Perfect Viewing Companion:If your product arrives damaged or breaks within 365 days, reach out to LISEN for a quick and hassle-free solution. Struggling with assembly, like tightening the screw? We’ve got your back! Your experience matters to us. (Product including: phone Holder stand*1, screw*1, hexagon screwdriver*1, specification*1)
[server]
ROOT_URL = https://git.example.com/

The trailing slash matters for generated links and redirects. The proxy must preserve encoded paths, pass the original host and protocol, and support WebSocket upgrades.

Example nginx proxy block

server {
    listen 80;
    server_name git.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name git.example.com;

    ssl_certificate     /etc/letsencrypt/live/git.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
    }
}

Use the complete certificate chain, reload nginx after validation, and test both a browser login and a repository operation. A missing X-Forwarded-Proto header commonly causes HTTPS redirect loops; missing upgrade headers break live notifications and other WebSocket-dependent features. If large repositories or release assets are uploaded, check nginx’s request-size and timeout settings rather than assuming the defaults are sufficient.

Use ACME without losing its state

Gitea can terminate TLS itself through built-in ACME, and it also supports nginx, Apache, and Caddy for TLS termination. With Docker, set ACME_DIRECTORY=/data/gitea/https and ensure that path is on the persistent /data mount. Recreating a container without the ACME account and certificate cache can cause repeated certificate requests. Let’s Encrypt limits certificates to five per week for the same set of domains, so test against a staging endpoint or preserve the cache when changing containers.

Back up Gitea so a restore is possible

Gitea explicitly states: “To ensure the consistency of the Gitea instance, it must be shutdown during backup.” Plan a maintenance window, stop the application, capture the files and database, then restart it. A snapshot taken while Gitea is writing can leave repositories and database records out of sync.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use the Gitea dump command

Run the command as the account that owns the installation, using the correct configuration path. In a binary installation the pattern is:

Rank #4
Ledagic IC+RGBW USB Powered Led Light Bar with App & Remote Control, 2 Pack
  • Easy Installation: Our gaming lights have been designed to enhance your entertainment experience. Simply position the led light bar next to your TV or game console to create a game room environment with ease. They come with USB power and a 60 inch cord for direct mounting and mobility
  • Audio Syncing & Extensive Mode: The built-in high-sensitivity music sensor allows you to sync the TV led lights to your favorite music. Lights react and move to the beat of music, film and game audio, creating an incredible immersive sound and light experience – and all without the need for an additional hub. You can choose from 64+ patterns, including strobe, illusion, jump, energy, gradient, running, chasing, fluttering mode etc. Each mode can be applied to different scenes
  • 64+ Chasing IC+RGB & W Effect: The independent control design of IC+RGB and white all-in-one multifunctional rgbw led bar lights monitor backlight allows you to easily switch the led lights for desk between IC+RGB and white to enjoy a variety of lighting effects, you can choose white lighting mode with high brightness for better illumination when working, etc. Choose IC+RGB lighting mode when you need to create an entertaining atmosphere for the light show, 16 million colours of Color changing rgb light bar let you dance to the beat and create a dynamic party atmosphere
  • Dynamic and Dimmable Lights: 1%-full brightness free brightness adjustment gives you the flexibility to adjust dimmable led light bar for room decorations or a variety of occasions
  • USB Powered: USB light bars for room can be powered by powernank, usb charger, TV, Monitor, laptop PC mainframe, making behind TV led lighting bar easy to install in any location.TV led lights are powered by the TV usb interface / PC mainframe, can be turned on/off synchronously with TV / PC
sudo systemctl stop gitea
sudo -u git /usr/local/bin/gitea dump -c /etc/gitea/app.ini
sudo systemctl start gitea

In a container deployment, run the equivalent command inside the container while the service is stopped, or use the image’s documented command invocation. The resulting ZIP contains app.ini when applicable, custom/, the data directory, complete repositories, gitea-db.sql, and logs.

Prefer native database dumps for external databases

For MySQL or PostgreSQL, administrators may prefer mysqldump or pg_dump. Record the database name, user, host, port, and credentials needed to restore it. Back up repository storage, attachments, packages, configuration, and secret material alongside the database; a database dump alone cannot reconstruct Git objects.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Store and test backups

  • Copy at least one backup off the VPS and protect it with access controls and encryption appropriate to your organization.
  • Keep a dated inventory of the Gitea version, image or binary, database version, mount points, and configuration paths used for each backup.
  • Periodically perform a restore rehearsal on an isolated VPS. Verify that users can log in, repositories clone and push, SSH keys work, hooks run, and attachments open.

Restore after data loss

Restoration is manual rather than a single guaranteed recovery command. Provision a compatible Linux host, install the same deployment type, and stop Gitea before replacing data.

  1. Install the matching Gitea release and create the expected git account, directories, and database engine.
  2. Unpack the dump and restore the database with the documented credentials. For native dumps, use the corresponding mysql or psql restore workflow.
  3. Copy repositories, custom/, attachments, packages, and app.ini into their original locations.
  4. Fix ownership and restrictive permissions. Configuration should not be readable by unrelated users.
  5. Start Gitea and inspect logs for missing paths, migrations, or database connection errors.
  6. If installation paths changed, regenerate repository hooks as part of the restore. Test clone, push, web login, SSH access, and WebSockets before declaring recovery complete.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Upgrade without breaking repositories

Docker upgrades

  1. Read the release notes and check database compatibility, especially when a PostgreSQL major image changes.
  2. Take and verify a backup while Gitea is stopped.
  3. Change the Compose image to the intended pinned version, pull it, and recreate the service:
    docker compose pull gitea
    docker compose up -d
  4. Watch logs for migrations and test browser access, HTTPS and SSH cloning, pushes, WebSocket notifications, large uploads, email, and database connectivity.

Keep the previous image tag available until the new instance passes these checks. Do not delete the persistent data directory as part of a routine container upgrade.

Binary upgrades

  1. Back up the instance and confirm the restore procedure.
  2. Download the architecture-matched release and verify its Sigstore or GPG signature.
  3. Stop Gitea, replace /usr/local/bin/gitea without changing the generic filename, and start the systemd unit again.
  4. Review journalctl -u gitea, allow migrations to finish, and run the same functional tests as a Docker upgrade.

Harden and operate the VPS

  • Set INSTALL_LOCK=true after the initial setup so the installer cannot be reopened.
  • Confirm that SECRET_KEY and INTERNAL_TOKEN are present and protected in the configuration.
  • Run Gitea as the dedicated non-root git account, whether it is inside a container or managed by systemd.
  • Expose only the ports you need: normally 80 and 443 for the reverse proxy and the selected SSH port for Git access. Keep Gitea’s internal web port private when nginx is local.
  • Patch the operating system, Docker Engine or binary, reverse proxy, and database on a planned schedule.
  • Monitor disk usage, memory, certificate expiry, container or systemd health, database availability, and backup job results.
  • Use a separate capacity plan when repositories, package artifacts, actions workloads, or attachments begin consuming significant storage or write throughput.

Troubleshoot the failures that matter most

The container starts but Gitea cannot write

Check whether the mounted directory is owned by the UID/GID expected by the selected rootful or rootless image. Correct ownership, confirm the filesystem is mounted read-write, and inspect container logs. Do not solve this by running the application as root or by making /data writable to everyone.

Best Value
Sale
HUANUO FlowLift™ Dual Monitor Stand, Fully Adjustable Gaming Monitor Desk Mount for 13–32″ Computer Screens, Full Motion VESA 75x75/100x100 with C-Clamp & Grommet Base, Each Arm Holds 4.4 to 19.8 lbs
  • Compatible with Wide Screens - To ensure compatibility with the dual monitor mount, your each monitor must meet three conditions at the same time: First, computer screens size range: 13 to 32 inches. Second, screen weight range: 4.4 to 19.8 lbs. Third, the back of the monitor screen must have VESA mounting holes with a pitch of 75x75mm or 100x100mm.
  • Regarding the compatibility with desks - Your desk must meet three conditions at the same time: First, desk material: Only wooden desks are recommended, plastic or glass desks cannot be used. Second, desk thickness range: 0.59" - 3.54". Third, the bottom of the desk should not have any cross beams or panels, as this will interfere with installation. We recommend carefully checking that your desk and monitors meets all above conditions before purchasing.
  • Dual C-Clamp Hold - Worried your dual monitors might wobble or slip? Our upgraded base uses a larger platform plus a dual C-clamp structure to lock the dual monitor arm firmly to your desk. Each arm safely keeps your screens steady while you type, click and game—no shaking, no sliding, just a clean and secure setup you can trust every day. It also provides Grommet Mounting installation choice, both options ensure stable and secure fixation for your 0.59" - 3.54" desk.
  • Full-Motion Adjustment For Comfortable View - Pull the screen closer when you’re deep in a spreadsheet, push it back to watch videos, or rotate to portrait for coding — moving everything smoothly with just one hand. The monitor stand offers +85°/-50° tilt, ±90° swivel and 360° rotation. Raise your monitor up to 15.75″ to support a healthy sitting posture. Whether you’re working from home, gaming through the night, or switching between video calls and documents, getting the screens to your natural line of sight helps relieve neck, shoulder and back strain so you can stay focused longer with less fatigue.
  • Keep Your Desk Organized: By lifting both screens off the desktop, this dual monitor stand opens up valuable space for your keyboard, notebook, docking station or a simple, clutter-free work area. Built-in cable management guides wires along the arms, keeping cords out of sight and out of the way. Enjoy a tidy, modern workstation that looks as good as it feels to use.

HTTPS redirects loop or links use HTTP

Verify ROOT_URL, ensure nginx sends X-Forwarded-Proto https, and confirm that the proxy passes the original host. Reload both services after changing configuration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Live notifications do not update

Check that nginx uses HTTP/1.1 and forwards both Upgrade and Connection headers. A normal page load can succeed even when WebSocket forwarding is wrong.

SSH clone fails while the web UI works

Confirm the VPS firewall, the published container port, and the SSH URL’s port. If Gitea listens on container port 22 but the host publishes 2222, clients must use 2222 or an SSH configuration alias.

A restore shows repositories but hooks fail

Check ownership and installation paths, then regenerate repository hooks. Hooks contain paths that can become invalid when moving from a container to a binary installation or to a different filesystem layout.

Which approach should you choose?

  • Choose Docker Compose with SQLite when you want the shortest path to a personal or low-write service and can keep /data on durable storage.
  • Choose Docker Compose with PostgreSQL or MySQL when you need a database service that can be managed, monitored, and scaled separately from Gitea.
  • Choose a binary with systemd when you prefer host-native process management, explicit filesystem permissions, and no container runtime.

In every case, the durable design is the same: private application listener, HTTPS reverse proxy, verified releases, non-root execution, tested backups, and a documented restore path.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Bottom Line

Self-hosted Gitea is straightforward on a VPS when storage and recovery are designed first. Use Docker Compose for repeatability or a verified binary for host-native control, keep /data and database state persistent, terminate TLS correctly, and never treat an untested backup as a recovery plan.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.