Skip to content
Deployments

Deploy a self-hosted git forge and CI with OpenTofu

Deployment

Deploy a self-hosted git forge and CI with OpenTofu

Stand up Forgejo with a bundled Forgejo Actions runner on one CPU VM using the validated OpenTofu template forgejo-git-ci. Forgejo Actions runs CI from the same workflow syntax as GitHub Actions. A data volume at /var/lib/forgejo holds repositories, CI artifacts, and the runner's Docker layers.

Monthly cost estimate

Pricing calculator ↗

Sized as a custom package on shared vCPU.

Starting template$33.60/mo

Monthly total for the required template above. Use the configurator below to add optional pieces and see the total update.

What each resource is for

Forgejo

s1a.medium · 4 shared vCPU, 4 GiB RAM, 0.5 Gbps

$33.00/mo

Compute shown per role at custom-package rates ($29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM). The headline above is the billed total: the cheaper of a named plan and the custom package, plus add-ons.

Included in baseline

s1a.medium

4 shared vCPU, 4 GiB RAM, 0.5 Gbps

$33.00

Compute + RAM rate basis

4 vCPU + 4 GiB RAM at $29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM (regular). Totals apply the flat −$5/mo package promotion.

—

Block storage (70 GiB)

70 GiB at $0.08/GiB/mo

$5.60

Public IP (included)

1 included with the custom package

$0.00

Package promotional discount

Flat −$5.00/mo on the custom package (same promotion as named plans).

$-5.00

Included at no charge

These line items are zero on Quake AI. Many other providers meter them separately.

Data transfer (inbound and outbound)

Unlimited data transfer on every plan; Quake AI does not meter per-GB egress.

AWS, GCP, and Azure meter outbound transfer per GB. DigitalOcean and Hetzner include an allowance on compute plans, then charge overage.

Learn more
$0.00

Private networking

Private networks, subnets, Neutron routers, and security groups are included with the plan.

VPC objects are usually free to create elsewhere, but NAT gateways bill hourly plus per-GB processed. Quake AI uses router SNAT with no separate NAT line item.

$0.00

Control-plane API requests

OpenStack API calls for provisioning and management are included.

Some managed services on other clouds meter API calls or charge for premium control-plane features.

$0.00

Pricing data last validated: . For current rates, check quake.ai/pricing.

Quake AIFloating IPweb + gitPrivate network10.40.0.0/24Routerto PublicStaticForgejo forge:80Actions runner(docker label)Data volume/var/lib/forgejo dispatch jobrepos + artifacts
Click to zoom
Forgejo git and CI topology: private subnet, forge and Actions runner with a data volume, and one floating IP

Prerequisites#

You need:

Step 1: Configure variables#

Copy terraform.tfvars.example to terraform.tfvars and set:

HCL
key_name = "YOUR_KEY_NAME"
# admin_username = "forgejo-admin"
# admin_email    = "[email protected]"
# domain         = "git.example.com"

Leave domain commented out to start on the floating IP over HTTP. Set domain later when you point DNS at the forge and configure TLS. Defaults match the Forgejo Git and CI reference page.

Step 2: Apply the template#

From the template directory, run:

bash
tofu init
tofu plan
tofu apply

Type yes when prompted. Cloud-init installs Docker, starts the forge and runner, creates the admin account, and registers the runner.

When the run finishes, record the outputs:

bash
WEB_URL=$(tofu output -raw web_url)
FORGE_IP=$(tofu output -raw floating_ip)
echo "$WEB_URL"

Step 3: Retrieve the admin password and sign in#

cloud-init takes a few minutes after apply returns. The admin password is written to /root/forgejo-credentials on the instance:

bash
ssh -i YOUR_PRIVATE_KEY_PATH -o StrictHostKeyChecking=accept-new ubuntu@"$FORGE_IP" 'cloud-init status --wait'
ssh -i YOUR_PRIVATE_KEY_PATH ubuntu@"$FORGE_IP" sudo cat /root/forgejo-credentials

Open web_url in your browser and sign in with the admin username and generated password. Rotate the password under Settings > Account, then delete the credentials file:

bash
ssh -i YOUR_PRIVATE_KEY_PATH ubuntu@"$FORGE_IP" sudo rm /root/forgejo-credentials

Step 4: Push a repository with a CI workflow#

Create a private repository named ci-demo in the forge UI. Generate a personal access token with the write:repository scope under Settings > Applications.

On your workstation:

bash
git clone "http://$FORGE_IP/forgejo-admin/ci-demo.git"
cd ci-demo
mkdir -p .forgejo/workflows
cat > .forgejo/workflows/ci.yml <<'YAML'
on: [push]

jobs:
  build:
    runs-on: docker
    steps:
      - uses: actions/checkout@v4
      - run: node --version
      - run: echo "CI is running on my own forge"
YAML
git add .forgejo/workflows/ci.yml
git commit -m "Add CI workflow"
git push origin main

Open the Actions tab in the ci-demo repository and confirm the run goes green. If the run stays queued, check Site Administration > Actions > Runners or read runner logs on the instance.

Step 5: Put a domain and TLS in front (optional)#

Set domain in terraform.tfvars, point the DNS A record at floating_ip, run tofu apply again, and terminate TLS with Forgejo ACME or a reverse proxy. See the template reference page for both paths.

Next steps#

Clean up#

Run tofu destroy from the project directory when finished. Type yes to confirm. Verify in the Console that the instance, data volume, and floating IP are gone.

Was this page helpful?