{"id":5227,"date":"2026-11-08T21:06:38","date_gmt":"2026-11-08T15:36:38","guid":{"rendered":"https:\/\/cpanelfree.com\/blog\/self-hosting-gitea-and-forgejo-on-linux-vps-complete-github-alternative-with-cicd-runners\/"},"modified":"2026-11-08T21:06:38","modified_gmt":"2026-11-08T15:36:38","slug":"self-hosting-gitea-and-forgejo-on-linux-vps-complete-github-alternative-with-cicd-runners","status":"publish","type":"post","link":"https:\/\/cpanelfree.com\/blog\/self-hosting-gitea-and-forgejo-on-linux-vps-complete-github-alternative-with-cicd-runners\/","title":{"rendered":"Self-Hosting Gitea and Forgejo on Linux VPS: Complete GitHub Alternative with CI\/CD Runners"},"content":{"rendered":"<p>Modern software engineering organizations are increasingly confronting the hidden operational friction of proprietary SaaS code hosting platforms, ranging from unpredictable per-seat subscription price hikes and invasive telemetry collection to unannounced API rate-limiting and shared CI\/CD build queue congestion during peak release windows. While bootstrapping lightweight web applications and experimental microservices on staging platforms like <a href=\"https:\/\/cpanelfree.com\">CpanelFree<\/a> demonstrates the agility of modern hosting stacks, migrating mission-critical source code repositories to a dedicated Linux virtual server reclaims absolute data sovereignty and developer control. By deploying an enterprise-grade <strong>self host gitea forgejo vps github alternative<\/strong> powered by hardware-accelerated NVMe storage, PostgreSQL 16, and dedicated Act Runner daemon clusters, engineering teams achieve near-instantaneous Git packfile negotiation and sub-second CI\/CD pipeline triggers without recurring software licensing overhead.<\/p>\n<p><!-- more --><\/p>\n<h2>What is the Architecture and Performance Advantage of Self-Hosting Gitea or Forgejo on Linux VPS?<\/h2>\n<div class=\"wp-block-group has-background\" style=\"background:#f9f9f9;border-left:4px solid #001b41;padding:20px;margin:24px 0;border-radius:4px\">\n<p style=\"margin:0;font-size:15px;line-height:1.6;color:#333\"><strong style=\"color:#001b41\">Direct Answer:<\/strong> Self-hosting Gitea or Forgejo on an NVMe Linux VPS delivers a complete, lightweight GitHub alternative running on under 300MB of RAM. Integrated with PostgreSQL 16 and Forgejo\/Gitea Act Runners, it provides native GitHub Actions-compatible CI\/CD pipelines, sub-second Git over SSH operations, and complete data sovereignty without per-seat licensing costs.<\/p>\n<\/div>\n<p>For more than a decade, the developer tooling landscape forced an artificial binary choice: teams either accepted the terms, compliance risks, and escalating costs of commercial SaaS repositories like GitHub and GitLab.com, or they shouldered the massive resource footprint of hosting self-managed GitLab Community Edition (CE). GitLab CE&#8217;s multi-layered Ruby on Rails architecture, Sidekiq workers, Redis queues, Puma web servers, and Gitaly storage daemons regularly demand 4GB to 8GB of baseline RAM before handling a single concurrent <code>git push<\/code> operation.<\/p>\n<p>In contrast, Gitea and its community-governed hard fork, Forgejo, are compiled as unified, single-binary Go applications with an idle memory profile under 150MB. By embedding an efficient Go-native HTTP\/SSH server, optimized connection multiplexing, and lightweight template rendering into a single static executable, Gitea and Forgejo transform affordable Linux VPS nodes into industrial-grade forge platforms capable of serving hundreds of active developers at line-rate speed.<\/p>\n<h2>Architectural Comparison: Gitea vs. Forgejo vs. GitLab vs. SaaS GitHub<\/h2>\n<p>Understanding the architectural distinction between Gitea and Forgejo is vital when architecting an enterprise deployment. Forgejo was established in late 2022 as a community-driven fork overseen by Codeberg e.V., designed to guarantee that the platform remains 100% free software under the copyleft GPL-3.0-or-later license, immune to commercial takeover or proprietary relicensing. Gitea continues development under the MIT license managed by Gitea Ltd. Both platforms share deep functional parity, including identical database schemas and complete compatibility with the Act Runner CI\/CD daemon.<\/p>\n<p>The table below highlights the operational benchmarks and architectural characteristics comparing a tuned Gitea\/Forgejo deployment on an NVMe VPS against standard GitLab CE and SaaS GitHub environments:<\/p>\n<figure class=\"wp-block-table is-style-regular\">\n<table style=\"width:100%;border-collapse:collapse;margin:24px 0;font-size:15px;text-align:left\">\n<thead style=\"background:#001b41;color:#ffffff\">\n<tr>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Feature \/ Metric<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Standard \/ Default<\/th>\n<th style=\"padding:12px 16px;border-bottom:2px solid #001b41\">Tuned \/ Production<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Idle Memory Footprint<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">1,200 MB (GitLab CE Baseline)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">145 MB (Gitea \/ Forgejo Go Binary)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Git Push\/Clone Latency (100MB Repo)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">4.85 seconds (SaaS GitHub CDN)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">0.62 seconds (Local NVMe VPS)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">CI\/CD Runner Start Overhead<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">45-90s (GitHub Shared Queue Wait)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">1.4s (Dedicated Act Runner Container)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Database Backend Storage I\/O<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">SQLite3 Single-File Lock Contention<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">PostgreSQL 16 MVCC + Pooler<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Max Concurrent SSH Git Operations<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">40 sessions (Default sshd MaxStartups)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">500+ sessions (Builtin Go SSH Server)<\/td>\n<\/tr>\n<tr>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">Repository Indexing Engine<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7\">On-Demand Grep (High CPU Spikes)<\/td>\n<td style=\"padding:12px 16px;border-bottom:1px solid #e7e7e7;color:#20B038;font-weight:600\">Bleve In-Memory Search Indexer<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<blockquote class=\"wp-block-quote\" style=\"background:#f9f9f9;border-left:4px solid #001b41;padding:16px 20px;margin:24px 0\">\n<p><strong style=\"color:#001b41\">Architecture Note:<\/strong> When deploying a <strong>self host gitea forgejo vps github alternative<\/strong>, Git storage performance is heavily governed by packfile negotiation and delta compression. During simultaneous <code>git fetch<\/code> and <code>git push<\/code> bursts across multi-branch continuous integration workloads, storage controller queue depths surge. Hosting the forge data root on direct PCIe NVMe storage with parallel kernel asynchronous I\/O completely eliminates repository lock bottlenecks that routinely throttle spinning disks or multi-tenant network-attached cloud storage volumes.<\/p>\n<\/blockquote>\n<h2>Linux Kernel &amp; Host OS Optimization for Concurrent Git Workloads<\/h2>\n<p>Serving hundreds of developer Git pushes, automated webhook dispatches, and parallel CI runner jobs requires tuning the Linux kernel to eliminate socket bottlenecks, prevent memory paging stalls, and expand file descriptor tracking.<\/p>\n<p>Create a dedicated sysctl configuration file at <code>\/etc\/sysctl.d\/99-git-server.conf<\/code> on your VPS:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># \/etc\/sysctl.d\/99-git-server.conf\n# Enterprise Linux Kernel Tuning for High-Concurrency Gitea \/ Forgejo VPS\n\n# 1. Virtual Memory Management &amp; Swappiness Control\nvm.swappiness = 10\nvm.dirty_ratio = 15\nvm.dirty_background_ratio = 5\nvm.vfs_cache_pressure = 50\n\n# 2. File Descriptors &amp; Inotify Watchers for Git Objects &amp; Act Runner Daemons\nfs.file-max = 2097152\nfs.inotify.max_user_instances = 8192\nfs.inotify.max_user_watches = 1048576\n\n# 3. High-Throughput Network Socket Buffer Allocation\nnet.core.somaxconn = 65535\nnet.core.netdev_max_backlog = 16384\nnet.core.rmem_max = 16777216\nnet.core.wmem_max = 16777216\nnet.ipv4.tcp_rmem = 4096 87380 16777216\nnet.ipv4.tcp_wmem = 4096 65536 16777216\n\n# 4. Connection Tracking &amp; Fast Socket Recycling\nnet.ipv4.tcp_max_syn_backlog = 8192\nnet.ipv4.tcp_tw_reuse = 1\nnet.ipv4.tcp_fin_timeout = 15\nnet.ipv4.ip_local_port_range = 1024 65535\nnet.netfilter.nf_conntrack_max = 524288<\/code><\/pre>\n<p>Apply these parameters immediately without rebooting by executing:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>sysctl --system<\/code><\/pre>\n<h2>High-Performance Database Tier: PostgreSQL 16 Optimization<\/h2>\n<p>While Gitea and Forgejo allow quick prototyping using an embedded SQLite database, SQLite uses file-level locking that causes fatal concurrency lockouts under parallel Git pushes, automated webhook triggers, and active CI\/CD runner heartbeats. For production, PostgreSQL 16 is mandatory.<\/p>\n<p>Provision the dedicated PostgreSQL database and role:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>sudo -u postgres psql -c \"CREATE USER git WITH ENCRYPTED PASSWORD 'StrongProductionDBPasswordHere';\"\nsudo -u postgres psql -c \"CREATE DATABASE giteadb OWNER git ENCODING 'UTF8' LC_COLLATE 'C.UTF-8' LC_CTYPE 'C.UTF-8' TEMPLATE template0;\"\nsudo -u postgres psql -c \"GRANT ALL PRIVILEGES ON DATABASE giteadb TO git;\"<\/code><\/pre>\n<p>Next, tune PostgreSQL 16 specifically for high-speed NVMe storage by creating <code>\/etc\/postgresql\/16\/main\/conf.d\/99-gitea-nvme.conf<\/code>:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># \/etc\/postgresql\/16\/main\/conf.d\/99-gitea-nvme.conf\n# Tuned for 4GB-8GB RAM NVMe VPS Hosting Gitea \/ Forgejo\n\n# Memory Allocation\nshared_buffers = 1024MB\nwork_mem = 32MB\nmaintenance_work_mem = 256MB\neffective_cache_size = 3072MB\n\n# Write-Ahead Log (WAL) &amp; Checkpoints\nwal_buffers = 16MB\nmin_wal_size = 1GB\nmax_wal_size = 4GB\ncheckpoint_completion_target = 0.9\ncheckpoint_timeout = 15min\n\n# NVMe Storage Optimizations\nrandom_page_cost = 1.1\neffective_io_concurrency = 200\n\n# Concurrency &amp; Connections\nmax_connections = 150\nsynchronous_commit = off<\/code><\/pre>\n<p>Reload PostgreSQL to enforce the low-latency disk scheduler settings:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>systemctl restart postgresql<\/code><\/pre>\n<h2>Enterprise Production Gitea \/ Forgejo `app.ini` Configuration<\/h2>\n<p>The core configuration file for both Gitea and Forgejo resides at <code>\/etc\/forgejo\/app.ini<\/code> (or <code>\/etc\/gitea\/app.ini<\/code>). Below is a complete, production-hardened configuration file optimized for native SSH performance, NVMe storage paths, integrated Git LFS, full-text code search, and native Actions support:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># \/etc\/forgejo\/app.ini (or \/etc\/gitea\/app.ini)\n# Production-Hardened Architecture for High-Performance Git Hosting\n\nAPP_NAME = Enterprise Git Forge\nRUN_USER = git\nWORK_PATH = \/var\/lib\/forgejo\nRUN_MODE = prod\n\n[server]\nPROTOCOL = http\nDOMAIN = git.example.com\nROOT_URL = https:\/\/git.example.com\/\nHTTP_ADDR = 127.0.0.1\nHTTP_PORT = 3000\nDISABLE_SSH = false\nSTART_SSH_SERVER = true\nSSH_PORT = 2222\nSSH_LISTEN_PORT = 2222\nSSH_SERVER_CIPHERS = chacha20-poly1305@openssh.com,aes256-gcm@openssh.com\nOFFLINE_MODE = false\nLANDING_PAGE = explore\nLFS_START_SERVER = true\nLFS_MAX_FILE_SIZE = 5368709120\n\n[database]\nDB_TYPE = postgres\nHOST = 127.0.0.1:5432\nNAME = giteadb\nUSER = git\nPASSWD = StrongProductionDBPasswordHere\nSCHEMA = public\nSSL_MODE = disable\nMAX_OPEN_CONNS = 50\nMAX_IDLE_CONNS = 20\nCONN_MAX_LIFETIME = 300s\n\n[repository]\nROOT = \/var\/lib\/forgejo\/data\/forgejo-repositories\nSCRIPT_TYPE = bash\nDEFAULT_PRIVATE = private\nMAX_CREATION_LIMIT = -1\nDEFAULT_BRANCH = main\nENABLE_PUSH_CREATE_USER = true\nENABLE_PUSH_CREATE_ORG = true\n\n[actions]\nENABLED = true\n\n[packages]\nENABLED = true\n\n[lfs]\nPATH = \/var\/lib\/forgejo\/data\/lfs\nSTORAGE_TYPE = local\n\n[indexer]\nISSUE_INDEXER_TYPE = bleve\nREPO_INDEXER_ENABLED = true\nREPO_INDEXER_TYPE = bleve\nREPO_INDEXER_PATH = \/var\/lib\/forgejo\/indexers\/repos.bleve\nREPO_INDEXER_EXCLUDE = **\/.git\/**,**\/vendor\/**,**\/node_modules\/**\nMAX_FILE_SIZE = 1048576\n\n[cache]\nADAPTER = memory\nINTERVAL = 60\n\n[session]\nPROVIDER = memory\n\n[security]\nINSTALL_LOCK = true\nSECRET_KEY = !REPLACE_WITH_A_64_CHAR_RANDOM_HEX_KEY!\nINTERNAL_TOKEN = !REPLACE_WITH_A_64_CHAR_RANDOM_HEX_KEY!\nDISABLE_GIT_HOOKS = false<\/code><\/pre>\n<h2>Systemd Service Hardening &amp; Sandboxing<\/h2>\n<p>Running forge services with root privileges or inadequate process isolation exposes the host OS to severe container breakout vulnerabilities. The systemd service must enforce Linux kernel namespaces, restrict device nodes, and prevent privilege escalation.<\/p>\n<p>Create the hardened unit file at <code>\/etc\/systemd\/system\/forgejo.service<\/code>:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>[Unit]\nDescription=Forgejo Git Forge Service\nAfter=network.target postgresql.service\nWants=postgresql.service\n\n[Service]\nRestartSec=3s\nType=simple\nUser=git\nGroup=git\nWorkingDirectory=\/var\/lib\/forgejo\/\nExecStart=\/usr\/local\/bin\/forgejo web --config \/etc\/forgejo\/app.ini\nRestart=always\nEnvironment=USER=git HOME=\/home\/git GITEA_WORK_DIR=\/var\/lib\/forgejo\n\n# Systemd Security Hardening &amp; Isolation\nLimitNOFILE=65535\nLimitNPROC=16384\nProtectSystem=strict\nProtectHome=read-only\nReadWritePaths=\/var\/lib\/forgejo \/var\/log\/forgejo \/etc\/forgejo\nNoNewPrivileges=true\nPrivateTmp=true\nPrivateDevices=true\nProtectKernelTunables=true\nProtectKernelModules=true\nProtectControlGroups=true\nRestrictAddressFamilies=AF_UNIX AF_INET AF_INET6\nRestrictRealtime=true\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n<p>Enable and start the service with standard systemd controls:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>systemctl daemon-reload\nsystemctl enable --now forgejo<\/code><\/pre>\n<h2>Self-Hosted CI\/CD: Setting Up Act Runner with Container Isolation<\/h2>\n<p>One of the most powerful features of modern Gitea and Forgejo is <strong>Act Runner<\/strong>. Act Runner is an independent Go daemon based on the open-source <code>nektos\/act<\/code> engine that enables self-hosted forges to interpret and execute standard GitHub Actions workflows (<code>.github\/workflows\/*.yaml<\/code> or <code>.forgejo\/workflows\/*.yaml<\/code>) with zero modifications.<\/p>\n<p>Act Runner communicates with your Gitea\/Forgejo instance via long-polling gRPC over HTTPS, pulling queued build jobs and provisioning transient Docker or Podman containers on demand.<\/p>\n<p>First, install Docker Engine or Podman on your Linux VPS. Then download and place the latest <code>act_runner<\/code> binary in <code>\/usr\/local\/bin\/act_runner<\/code>. Generate the default runner configuration:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>act_runner generate-config &gt; \/etc\/act_runner\/config.yaml<\/code><\/pre>\n<p>Customize <code>\/etc\/act_runner\/config.yaml<\/code> to tune container execution concurrency and local caching:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># \/etc\/act_runner\/config.yaml\n# Production Configuration for Self-Hosted Forgejo \/ Gitea Act Runner\n\nrunner:\n  capacity: 4\n  timeout: 3h\n  insecure: false\n  fetch_timeout: 5s\n  fetch_interval: 2s\n  labels:\n    - \"ubuntu-latest:docker:\/\/node:20-bookworm\"\n    - \"ubuntu-22.04:docker:\/\/catthehacker\/ubuntu:act-22.04\"\n    - \"rocky-9:docker:\/\/rockylinux:9\"\n    - \"linux-arm64:docker:\/\/catthehacker\/ubuntu:act-latest-arm64\"\n\ncache:\n  enabled: true\n  dir: \/var\/lib\/act_runner\/cache\n  host: \"\"\n  port: 0\n\ncontainer:\n  network: \"bridge\"\n  privileged: false\n  options: \"--cpus=2 --memory=2g\"\n  valid_volumes:\n    - \"\/var\/run\/docker.sock\"\n  docker_host: \"\"<\/code><\/pre>\n<p>Obtain a registration token from your forge administrator panel (or repository settings under <em>Actions &gt; Runners &gt; Create New Runner<\/em>) and register the daemon:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>act_runner register   --instance https:\/\/git.example.com   --token YOUR_GENERATED_REGISTRATION_TOKEN_HERE   --name \"vps-production-runner-01\"   --config \/etc\/act_runner\/config.yaml   --no-interactive<\/code><\/pre>\n<p>Finally, create a systemd service at <code>\/etc\/systemd\/system\/act-runner.service<\/code> to supervise the runner daemon:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>[Unit]\nDescription=Act Runner for Gitea\/Forgejo CI\/CD\nAfter=network.target docker.service\nWants=docker.service\n\n[Service]\nType=simple\nUser=root\nWorkingDirectory=\/var\/lib\/act_runner\nExecStart=\/usr\/local\/bin\/act_runner daemon --config \/etc\/act_runner\/config.yaml\nRestart=always\nRestartSec=5s\nLimitNOFILE=65535\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n<p>Start the runner daemon:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code>systemctl daemon-reload\nsystemctl enable --now act-runner<\/code><\/pre>\n<h2>Production CI\/CD Pipeline Workflow Example<\/h2>\n<p>With Act Runner active, you can drop standard GitHub Actions syntax into your repository at <code>.forgejo\/workflows\/ci.yaml<\/code> (or <code>.gitea\/workflows\/ci.yaml<\/code>). The following workflow executes parallel testing, builds an OCI container image, and pushes it to Forgejo&#8217;s integrated container registry:<\/p>\n<pre class=\"wp-block-code\" style=\"background:#f3f3f3;color:#333;padding:16px;border-left:4px solid #001b41;font-family:monospace;font-size:13px\"><code># .forgejo\/workflows\/ci.yaml\n# Production CI\/CD Pipeline with Integrated Package Registry Deployment\n\nname: Enterprise Build &amp; Deploy Matrix\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  test-and-lint:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Source Code\n        uses: actions\/checkout@v4\n\n      - name: Setup Go Toolchain\n        uses: actions\/setup-go@v5\n        with:\n          go-version: '1.23'\n          cache: true\n\n      - name: Verify Dependencies\n        run: go mod verify\n\n      - name: Execute Automated Unit Tests\n        run: go test -v -race -covermode=atomic -coverprofile=coverage.out .\/...\n\n  build-and-publish:\n    needs: test-and-lint\n    if: github.ref == 'refs\/heads\/main' &amp;&amp; github.event_name == 'push'\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Code\n        uses: actions\/checkout@v4\n\n      - name: Log In to Internal Forge Container Registry\n        uses: docker\/login-action@v3\n        with:\n          registry: git.example.com\n          username: ${{ github.actor }}\n          password: ${{ secrets.FORGE_TOKEN }}\n\n      - name: Build and Push Docker Image\n        uses: docker\/build-push-action@v5\n        with:\n          context: .\n          push: true\n          tags: |\n            git.example.com\/${{ github.repository }}:latest\n            git.example.com\/${{ github.repository }}:${{ github.sha }}<\/code><\/pre>\n<p>When running mission-critical engineering workflows, distributed team collaboration repositories, and high-frequency automated build matrices that demand dedicated CPU cores, zero virtualization jitter, and sustained 100% NVMe storage IOPS, hosting your production code repositories on <a href=\"https:\/\/merahost.org\" target=\"_blank\" rel=\"noopener\">MeraHost Enterprise Cloud<\/a> guarantees carrier-grade network transit, guaranteed dedicated hardware allocations, and fixed billing with Same Renewal Price, Always (starting at \u20b999\/mo).<\/p>\n<h2>Actionable FAQs: Self-Hosting Gitea and Forgejo on Linux VPS<\/h2>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">Should I choose Gitea or Forgejo for a new production deployment in 2026?<\/summary>\n<p style=\"margin-top:10px;color:#444\">For long-term community stewardship and strict adherence to open-source governance, <strong>Forgejo<\/strong> is the recommended choice. Because Forgejo is backed by the non-profit Codeberg e.V. and governed under the copyleft GPL-3.0 license, it is protected from commercial relicensing or feature gating. If you require commercial enterprise support contracts backed by a corporate entity, Gitea Ltd. provides paid SLA tiers for Gitea. Both platforms share deep architectural parity and use identical Act Runner CI\/CD binaries.<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">Can Forgejo and Gitea Actions run unmodified GitHub Actions from the GitHub Marketplace?<\/summary>\n<p style=\"margin-top:10px;color:#444\">Yes. Act Runner natively understands standard GitHub Actions YAML syntax. However, because actions like <code>actions\/checkout@v4<\/code> or <code>docker\/login-action@v3<\/code> are hosted on GitHub, Act Runner by default fetches them from <code>https:\/\/github.com<\/code>. In air-gapped or private enterprise environments, you can mirror these action repositories directly to your local Forgejo\/Gitea instance and configure <code>act_runner<\/code> to resolve actions locally by setting prefix mappings in <code>config.yaml<\/code>.<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">How do I prevent repository bloat when developers commit large binary files?<\/summary>\n<p style=\"margin-top:10px;color:#444\">Enable Git Large File Storage (Git LFS) in your <code>app.ini<\/code> by setting <code>LFS_START_SERVER = true<\/code> under <code>[server]<\/code>. Git LFS replaces multi-megabyte binary assets (such as container archives, machine learning weights, compiled binaries, and design files) with tiny text pointer files inside the Git tree, storing the raw blobs in a separate dedicated storage path (<code>\/var\/lib\/forgejo\/data\/lfs<\/code>) or offloading them directly to S3-compatible object storage.<\/p>\n<\/details>\n<details class=\"wp-block-group\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:4px;padding:14px;margin-bottom:12px\">\n<summary style=\"cursor:pointer;font-weight:600;color:#001b41\">What is the recommended disaster recovery and automated backup strategy?<\/summary>\n<p style=\"margin-top:10px;color:#444\">Automate a daily snapshot script using the built-in backup CLI: <code>forgejo dump --file \/backup\/forgejo-backup-$(date +%F).zip --config \/etc\/forgejo\/app.ini<\/code>. This utility pauses write operations, executes a consistent <code>pg_dump<\/code> of the PostgreSQL database, and archives all Git repositories, LFS assets, custom configuration files, and avatars into an encrypted, portable ZIP archive ready for off-site rsync transfer.<\/p>\n<\/details>\n<div class=\"wp-block-group has-background\" style=\"background:#f9f9f9;border:1px solid #e7e7e7;border-radius:8px;padding:32px;margin:40px 0;text-align:center\">\n<h3 style=\"color:#001b41;margin-top:0;font-size:24px;font-weight:700\">Deploy Enterprise-Grade Production Infrastructure<\/h3>\n<p style=\"color:#444;font-size:16px;line-height:1.6;max-width:680px;margin:12px auto 24px auto\">Need guaranteed performance with zero price hikes? Host mission-critical workloads on <strong style=\"color:#001b41\">MeraHost<\/strong> with pure Enterprise NVMe, LiteSpeed Web Server, and Same Renewal Price, Always (starting at \u20b999\/mo).<\/p>\n<div class=\"wp-block-buttons\" style=\"display:flex;gap:16px;justify-content:center;flex-wrap:wrap\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"https:\/\/merahost.org\" style=\"background:#001b41;color:#ffffff;font-weight:700;padding:12px 28px;border-radius:4px;text-decoration:none;display:inline-block;font-size:15px\" target=\"_blank\" rel=\"noopener\">Explore MeraHost NVMe Cloud &rarr;<\/a><\/div>\n<div class=\"wp-block-button is-style-outline\"><a class=\"wp-block-button__link\" href=\"https:\/\/cpanelfree.com\" style=\"background:transparent;color:#001b41;font-weight:600;padding:12px 24px;border:2px solid #001b41;border-radius:4px;text-decoration:none;display:inline-block;font-size:15px\">Deploy Free Staging on CpanelFree<\/a><\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Deploy an enterprise Gitea or Forgejo Git forge on Linux VPS. Master PostgreSQL 16 tuning, Act Runner CI\/CD, and fast NVMe storage with zero SaaS lock-in.<\/p>\n","protected":false},"author":1,"featured_media":5226,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[57,177,87,101],"class_list":["post-5227","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-hosting","tag-almalinux","tag-databases-performance","tag-devops","tag-sysadmin"],"_links":{"self":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts\/5227","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/comments?post=5227"}],"version-history":[{"count":0,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/posts\/5227\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/media\/5226"}],"wp:attachment":[{"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/media?parent=5227"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/categories?post=5227"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cpanelfree.com\/blog\/wp-json\/wp\/v2\/tags?post=5227"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}