[{"data":1,"prerenderedAt":191},["ShallowReactive",2],{"seo-verification":3,"blog-host-forgejo-on-your-own-vps-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"slugs":9,"title":12,"excerpt":13,"readTime":14,"views":15,"isPinned":16,"publishedAt":17,"category":18,"categories":24,"featuredImage":26,"bgImage":27,"posterImage":28,"relatedSolution":26,"intro":29,"sections":30,"ctaTitle":136,"ctaBody":137,"ctaButton":138,"ctaUrl":139,"relatedPosts":140},75,"host-forgejo-on-your-own-vps",{"fr":10,"en":8,"ar":11},"heberger-forgejo","استضافة-forgejo-على-خادم-vps-الخاص-بك","Self-Host Forgejo on Your VPS: Complete 2025 Guide","Deploy Forgejo on your VPS with Docker, SSL, Actions runners and hardened security. Step-by-step guide for a sovereign Git forge.",10,1,false,"2026-04-06T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":23},7,"Self-hosting","self-hosting","bg-indigo-500\u002F10 text-indigo-400","cloud",[25],{"id":19,"name":20,"slug":21,"color":22,"icon":23},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fheberger-forgejo-poster.svg","Forgejo is the lightweight, community-driven Git forge that emerged as an alternative to Gitea. Compatible with GitHub Actions, easy to migrate to, and respectful of your data, it can be running on a VPS in under an hour. This guide covers everything: server sizing, Docker deployment, SSL configuration, CI\u002FCD runners, post-install hardening and zero-downtime updates.",[31,35,47,50,72,75,78,81,85,88,91],{"type":32,"title":33,"body":34},"h2","Why Choose Forgejo for Your Self-Hosted Git Forge","Forgejo was born in 2022 as a community fork of Gitea, driven by concerns about the project's governance. Its development is entirely community-led, MIT-licensed, with no dependency on a commercial entity. For teams wanting full control over their source code, CI\u002FCD pipelines, and artifacts without relying on GitHub, GitLab, or Bitbucket, Forgejo is the lightest option available. The interface will feel familiar to any GitHub user, migration from Gitea is seamless, and GitHub Actions compatibility lowers the barrier to adoption.",{"type":36,"title":37,"items":38},"ul","Concrete Benefits of a Self-Hosted Forgejo",[39,40,41,42,43,44,45,46],"Full sovereignty: your code never leaves your infrastructure","GitHub Actions compatible via Forgejo Actions — reuse existing workflows","Minimal memory footprint (256 MB RAM for a small team)","Built-in package registry: npm, PyPI, Maven, Helm, OCI container","No limits on private repositories or collaborators","ActivityPub federation in progress — future interoperability with other forges","Open-source, auditable, no pricing surprises","Controlled updates: you decide when to upgrade",{"type":32,"title":48,"body":49},"Hardware and Software Requirements with Real Numbers","Size your VPS according to your actual team size before deploying Forgejo. For 1–5 developers with a few dozen repositories, 1 vCPU and 1 GB RAM are sufficient; Forgejo at rest uses around 80 MB. For 5–20 developers with active CI\u002FCD, plan for 2 vCPU and 2 GB RAM. Beyond 20 developers or for large repositories (monorepos, binaries), 4 vCPU and 4 GB RAM ensure a smooth experience. For storage, account for your Git repository volume plus 20% headroom for artifacts and backups.\n\nOn the network side, three ports must be open in your firewall: port 80 (HTTP, for Let's Encrypt validation), port 443 (HTTPS, web traffic), and port 2222 (Git SSH, to avoid conflicting with the admin SSH on port 22). On the software side, you need Docker Engine ≥ 24, Docker Compose v2, and a domain name pointing to your VPS.",{"type":51,"title":52,"steps":53},"steps","Deploy Forgejo with Docker and SSL",[54,57,60,63,66,69],{"title":55,"body":56},"Prepare the environment","Create the directories that will persist data outside the container:\n\n```bash\nmkdir -p \u002Fopt\u002Fforgejo\u002F{data,config,db}\nchown -R 1000:1000 \u002Fopt\u002Fforgejo\n```\n\nCreate `\u002Fopt\u002Fforgejo\u002F.env` with your values:\n\n```env\nFORGEJO_DOMAIN=git.yourdomain.com\nFORGEJO_SSH_PORT=2222\nPOSTGRES_PASSWORD=change_this_password\n```",{"title":58,"body":59},"Create the docker-compose.yml","```yaml\nservices:\n  forgejo:\n    image: codeberg.org\u002Fforgejo\u002Fforgejo:latest\n    restart: unless-stopped\n    environment:\n      - USER_UID=1000\n      - USER_GID=1000\n      - FORGEJO__database__DB_TYPE=postgres\n      - FORGEJO__database__HOST=db:5432\n      - FORGEJO__database__NAME=forgejo\n      - FORGEJO__database__USER=forgejo\n      - FORGEJO__database__PASSWD=${POSTGRES_PASSWORD}\n    volumes:\n      - \u002Fopt\u002Fforgejo\u002Fdata:\u002Fdata\n    ports:\n      - \"3000:3000\"\n      - \"${FORGEJO_SSH_PORT:-2222}:22\"\n    depends_on:\n      - db\n\n  db:\n    image: postgres:16-alpine\n    restart: unless-stopped\n    environment:\n      - POSTGRES_DB=forgejo\n      - POSTGRES_USER=forgejo\n      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}\n    volumes:\n      - \u002Fopt\u002Fforgejo\u002Fdb:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata\n```",{"title":61,"body":62},"Start the services","```bash\ncd \u002Fopt\u002Fforgejo\ndocker compose up -d\ndocker compose logs -f forgejo\n```\n\nWait for the `Listen on :3000` line to appear. Forgejo runs its schema migrations automatically on first start.",{"title":64,"body":65},"Configure the reverse proxy and SSL with Caddy","Caddy is the simplest option for automatic Let's Encrypt certificates. Install it and create `\u002Fetc\u002Fcaddy\u002FCaddyfile`:\n\n```\ngit.yourdomain.com {\n  reverse_proxy localhost:3000\n}\n```\n\nStart Caddy: `systemctl enable --now caddy`. The TLS certificate is issued and renewed automatically. If you prefer nginx, configure a standard `proxy_pass http:\u002F\u002F127.0.0.1:3000;` block with Certbot.",{"title":67,"body":68},"Complete the instance setup","Open `https:\u002F\u002Fgit.yourdomain.com` in your browser. The setup wizard appears once only. Fill in the domain, the SSH URL (`ssh:\u002F\u002Fgit.yourdomain.com:2222`), the admin email address, and disable public registration on this screen if your forge is for private use. Once the wizard is submitted, the configuration is locked in `\u002Fopt\u002Fforgejo\u002Fdata\u002Fgitea\u002Fconf\u002Fapp.ini`.",{"title":70,"body":71},"Install a Forgejo Actions runner","On the same server or a dedicated machine, retrieve the token from *Site Administration → Runners*. Deploy the runner via Docker:\n\n```yaml\nservices:\n  runner:\n    image: code.forgejo.org\u002Fforgejo\u002Fact_runner:latest\n    restart: unless-stopped\n    environment:\n      - FORGEJO_INSTANCE_URL=https:\u002F\u002Fgit.yourdomain.com\n      - FORGEJO_RUNNER_TOKEN=your_token\n      - FORGEJO_RUNNER_NAME=primary-runner\n      - FORGEJO_RUNNER_LABELS=ubuntu-latest:docker:\u002F\u002Fnode:20,docker:docker:\u002F\u002Fdocker:dind\n    volumes:\n      - \u002Fvar\u002Frun\u002Fdocker.sock:\u002Fvar\u002Frun\u002Fdocker.sock\n```\n\nThe runner appears in the interface within a minute. It can execute jobs in **Docker** mode (full isolation, recommended), **Process** mode (without Docker, for lightweight shell tasks), or **Auto** (detects based on the workflow label).",{"type":32,"title":73,"body":74},"Writing Your First Forgejo Actions Workflows","Compatibility with GitHub Actions syntax is broad. Create `.forgejo\u002Fworkflows\u002Fci.yml` at the root of your repository:\n\n```yaml\non:\n  push:\n    branches: [main]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - name: Run tests\n        run: |\n          npm ci\n          npm test\n```\n\nThe `runs-on` labels correspond to the labels declared when registering the runner. You can define multiple runners with different labels (e.g., `arm64`, `gpu`, `high-memory`) and target the right environment per job. Artifacts and caching work with the same official actions as on GitHub.",{"type":32,"title":76,"body":77},"Post-Install Security: Essential Settings","A freshly installed Forgejo is functional but not hardened. Here are the six points to address before opening the forge to your team.\n\n**Disable public registration.** In *Site Administration → Settings → Users*, uncheck \"Allow user registration\". On an internal forge, nobody should be able to create an account without an invitation.\n\n**Enable 2FA for administrators.** Every admin account must enable two-factor authentication under *Settings → Security*. Enforce 2FA for all users via the `REQUIRE_SIGNIN_VIEW` setting and organizational security policies.\n\n**SSH keys only.** Disable password authentication in the host server's `\u002Fetc\u002Fssh\u002Fsshd_config` (`PasswordAuthentication no`). For Git SSH (port 2222), Forgejo only accepts public keys registered in user profiles — this is its default behavior.\n\n**Webhook secrets.** When creating each webhook (to external CI, Slack, etc.), always fill in the *Secret* field. Forgejo signs the payload with HMAC-SHA256; your receiver must verify this signature before processing the event.\n\n**Private packages.** If you use the built-in package registry, set the default visibility to *Private* in organization settings. Access tokens for publishing should have minimal scope (`packages:write` only, never a global admin token).\n\n**Firewall.** Close all ports except 80, 443, and 2222. Port 3000 (internal Forgejo) must never be exposed directly; it is consumed only by the reverse proxy on loopback.",{"type":32,"title":79,"body":80},"Updating Forgejo Without Downtime","The Docker update procedure is straightforward and requires only a few seconds of unavailability.\n\n```bash\ncd \u002Fopt\u002Fforgejo\n# 1. Pull the new image\ndocker compose pull forgejo\n\n# 2. Back up the database before any migration\ndocker compose exec db pg_dump -U forgejo forgejo > backup-$(date +%Y%m%d).sql\n\n# 3. Restart the service\ndocker compose up -d forgejo\n\n# 4. Verify schema migrations\ndocker compose logs forgejo | grep -i migrat\n```\n\nForgejo runs its migrations automatically on startup. Verify that a `Finished successfully` line appears in the logs. In case of a migration error, restore the SQL backup and report the issue on the Forgejo tracker. Always read the release notes before jumping major versions — major version migrations may require an intermediate step.",{"type":82,"title":83,"body":84},"tip","Migrate from Gitea in Five Minutes","Forgejo is a direct fork of Gitea: its database schema is compatible up to version 1.21. To migrate, stop Gitea, copy its data directory (`\u002Fdata` or `\u002Fopt\u002Fgitea`) to `\u002Fopt\u002Fforgejo\u002Fdata`, replace the image in your docker-compose, and restart. Forgejo automatically detects the Gitea schema and applies its own migrations. Your repositories, users, SSH keys, webhooks, and issues are fully preserved. For newer Gitea versions, check the compatibility matrix on the Forgejo wiki before migrating.",{"type":32,"title":86,"body":87},"Troubleshooting: Most Common Errors","**SSH connection refused on port 2222.** First verify the port is published by Docker (`docker compose ps` → Ports column). Then test from the client: `ssh -p 2222 git@git.yourdomain.com`. If the response is `PTY allocation request failed`, the connection is working — Forgejo responds `Hi \u003Cuser>! You've successfully authenticated`. If you get `Connection refused`, the firewall is blocking the port: `ufw allow 2222\u002Ftcp`.\n\n**Runner showing offline in the interface.** The runner contacts Forgejo over outbound HTTPS. Verify the runner container can resolve and reach `git.yourdomain.com`. A self-signed certificate requires mounting your CA in the container. Restart the runner after fixing connectivity: `docker compose restart runner`.\n\n**Push rejected by a pre-receive hook.** Forgejo may reject a push if a branch protection rule is active (code review required, mandatory CI tests) or if a file size rule is exceeded. The git error message contains the details. For large binaries (> 100 MB), use Git LFS: Forgejo supports the LFS protocol natively.\n\n**Slow interface after several months.** Run the Git garbage collector on active repositories from the admin panel: *Administration → Repositories → Git Repositories → Run Git GC*. To automate this, configure the scheduled task in `app.ini` under `[cron.run_task]`.",{"type":82,"title":89,"body":90},"ActivityPub Federation: What Forgejo Is Building","Forgejo is the first Git forge project to implement federation via the ActivityPub protocol (the same one used by Mastodon). As of version 1.20+, you can already follow a remote repository hosted on another federated Forgejo instance and receive issue and pull request notifications in your local timeline. Full federation — cross-instance forking, inter-forge pull requests — is being standardized within the ForgeFed working group. If your collaborators are on different forges, this evolution will eventually allow contributing without creating an account on each instance.",{"type":92,"title":93,"headers":94,"rows":99},"comparison","Forgejo vs Gitea vs GitLab CE: Choosing Your Forge",[95,96,97,98],"Criterion","Forgejo","Gitea","GitLab CE",[100,105,109,114,118,122,125,129,133],[101,102,103,104],"Governance","Community (Codeberg e.V.)","Commercial (Gitea Ltd)","Commercial (GitLab Inc)",[106,107,107,108],"Minimum RAM","~80 MB","~4 GB",[110,111,112,113],"GitHub Actions compatibility","Yes (Forgejo Actions)","Yes (Gitea Act)","No (proprietary CI)",[115,116,117,117],"Package registry","Yes (multi-format)","Yes",[119,120,121,121],"ActivityPub federation","In progress (ForgeFed)","No",[123,124,117,117],"Migration from GitHub","Yes (mirror + import)",[126,127,127,128],"Admin interface","Simple, built-in","Full-featured but heavy",[130,131,131,132],"License","MIT","MIT (CE) \u002F EE (paid)",[134,135,135,135],"Release frequency","Monthly","A VPS ready for Forgejo in minutes","Our VPS Cloud range gives you a clean Debian or Ubuntu server, SSD storage and a dedicated IP. One `docker compose up` later, your forge is live.","See our VPS Cloud plans","\u002Fvps-cloud",[141,156,174],{"id":142,"slug":143,"slugs":144,"title":147,"excerpt":148,"readTime":149,"views":150,"isPinned":16,"publishedAt":151,"category":152,"categories":153,"featuredImage":26,"bgImage":27,"posterImage":155,"relatedSolution":26},261,"when-saas-vendors-bundle-ai-migrating-to-self-hosting",{"fr":145,"en":143,"ar":146},"migrer-saas-self-hosting-bundling-ia","ارتفاع-تكاليف-saas-46-متى-تستضيف-بنفسك","When SaaS vendors bundle AI: migrating to self-hosting","PricePulse H1 2026: +46% SaaS costs for 50-person teams. Mattermost, Nextcloud, Plane and Forgejo self-host on a VPS. Migration guide.",9,0,"2026-08-14T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":23},[154],{"id":19,"name":20,"slug":21,"color":22,"icon":23},"\u002Fblog\u002Fcovers\u002Fmigrer-saas-self-hosting-bundling-ia-poster.svg",{"id":157,"slug":158,"slugs":159,"title":162,"excerpt":163,"readTime":164,"views":150,"isPinned":16,"publishedAt":165,"category":166,"categories":171,"featuredImage":26,"bgImage":27,"posterImage":173,"relatedSolution":26},229,"docker-compose-in-production-10-point-checklist",{"fr":160,"en":158,"ar":161},"docker-compose-production-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","Docker Compose in Production: 10-Point Checklist","10 Docker Compose settings to verify before any production deployment: restart, healthchecks, limits, secrets and logs.",14,"2026-08-06T00:00:00+00:00",{"id":167,"name":168,"slug":169,"color":170,"icon":169},3,"Deployment","deploiement","bg-success\u002F10 text-success",[172],{"id":167,"name":168,"slug":169,"color":170,"icon":169},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",{"id":175,"slug":176,"slugs":177,"title":180,"excerpt":181,"readTime":14,"views":150,"isPinned":16,"publishedAt":165,"category":182,"categories":188,"featuredImage":26,"bgImage":27,"posterImage":190,"relatedSolution":26},228,"initial-linux-server-hardening",{"fr":178,"en":176,"ar":179},"durcissement-serveur-linux-initial","تصليب-الخادم-linux-الأولي","Initial Linux Server Hardening","Create a sudo user, configure SSH with keys, enable UFW and fail2ban on Ubuntu 22.04 or Debian 12 in under an hour.",{"id":183,"name":184,"slug":185,"color":186,"icon":187},8,"Security & Monitoring","securite-monitoring","bg-rose-500\u002F10 text-rose-400","security",[189],{"id":183,"name":184,"slug":185,"color":186,"icon":187},"\u002Fblog\u002Fcovers\u002Fdurcissement-serveur-linux-initial-poster.svg",1787580998390]