Streamlining CI/CD: How to Configure Gitea Actions for Docker Builds and GHCR Publishing on a Private VPS
Introduction
In the modern software development lifecycle, continuous integration and continuous deployment (CI/CD) have evolved from luxury practices to absolute necessities. While cloud-native platforms like GitHub Actions and GitLab CI dominate the enterprise landscape, many organizations, independent developers, and privacy-conscious teams prefer the autonomy and cost-efficiency of hosting their own infrastructure. Gitea, a lightweight, self-hosted Git service written in Go, has emerged as a premier alternative to resource-heavy platforms.
With the introduction of Gitea Actions—a built-in CI/CD engine compatible with GitHub Actions workflow syntax—developers can now enjoy the best of both worlds. This article provides a comprehensive, step-by-step guide on how to configure Gitea Actions on your private Virtual Private Server (VPS) to automatically build and push Docker images to the GitHub Container Registry (GHCR). By leveraging this architecture, you maintain absolute control over your source code repositories while offloading artifact storage to GitHub’s robust, global infrastructure.
---Why Pair Gitea Actions with GitHub Container Registry?
Before diving into the technical implementation, it is crucial to understand the architectural benefits of this specific hybrid setup:
- Resource Efficiency: Running a local Docker registry on a modest VPS can quickly consume limited disk space and memory. Utilizing GHCR as your artifact repository shifts the storage burden away from your private server.
- Seamless Workflow Compatibility: Gitea Actions uses the same YAML syntax as GitHub Actions. This drastically lowers the learning curve and allows you to repurpose existing community actions.
- Security and Isolation: Your source code remains strictly private on your self-hosted VPS, while public or private container deployment images are securely pushed to GHCR with granular access tokens.
Prerequisites and System Requirements
To follow along with this tutorial successfully, ensure you have the following prerequisites ready on your private VPS:
- A fully functional instance of Gitea (version 1.19 or higher) running on your VPS.
- Root or sudo access to your VPS terminal.
- Docker and Docker Compose installed on the host machine.
- A GitHub account with an generated Personal Access Token (PAT) possessing
write:packagesandread:packagespermissions.
Step 1: Enabling Gitea Actions on Your VPS
By default, Gitea Actions may be disabled depending on your initial configuration. To enable the system, you must modify your Gitea configuration file (usually located at /data/gitea/conf/app.ini or equivalent depending on your installation path).
Open the file using your preferred text editor and append the following configuration block:
[actions]ENABLED = true
Save the file and restart your Gitea service using systemd or Docker Compose to apply the changes:
sudo systemctl restart giteaOnce restarted, you will notice an "Actions" tab appear in your Gitea repository settings.
---Step 2: Registering and Configuring the Gitea Runner (act_runner)
Gitea Actions requires a separate daemon called act_runner to execute the workflows. It is highly recommended to run this runner inside an isolated Docker container on your VPS to ensure a clean build environment.
1. Generate the Registration Token
Navigate to your Gitea web interface. Go to Site Administration > Actions > Runners and click on Create New Runner. Copy the registration token provided; you will need this in the next sub-step.
2. Deploy the Runner via Docker Compose
Create a dedicated directory for your runner and set up a docker-compose.yml file:
mkdir gitea-runner && cd gitea-runnernano docker-compose.ymlPaste the following service definition into the file:
version: '3.8'services:runner:image: gitea/act_runner:latestenvironment:- GITEA_INSTANCE_URL=http://your-vps-ip:3000- GITEA_RUNNER_REGISTRATION_TOKEN=YOUR_COPIED_TOKEN- GITEA_RUNNER_NAME=vps-docker-runnervolumes:- /var/run/docker.sock:/var/run/docker.sock- ./data:/datarestart: always
Run docker-compose up -d to initialize and register your runner. Verify its status in the Gitea admin panel; it should now show as Idle and ready for jobs.
Step 3: Setting Up Repository Secrets
To push images securely to GHCR, your CI/CD pipeline needs authentication details. Rather than hardcoding these credentials, we utilize Gitea Secrets.
Navigate to your specific repository in Gitea, click Settings > Actions > Secrets, and add the following two secrets:
- GHCR_USERNAME: Your literal GitHub username.
- GHCR_TOKEN: The Personal Access Token (PAT) generated from GitHub with package write permissions.
Step 4: Writing the CI/CD Workflow File
Gitea detects workflow files located within the .gitea/workflows/ directory at the root of your repository. Create a file named release.yaml inside that path and populate it with the configuration below:
name: Build and Push Docker Image to GHCR
on:
push:
branches:
- main
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Log in to GitHub Container Registry
uses: actions/docker-login@v2
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Build and Push Docker Image
run: |
IMAGE_NAME=ghcr.io/${{ secrets.GHCR_USERNAME }}/my-app:latest
docker build -t $IMAGE_NAME .
docker push $IMAGE_NAMENote: Ensure your project repository includes a valid Dockerfile in the root directory for the docker build command to succeed seamlessly.
Step 5: Testing and Validating the Pipeline
With the runner online and the workflow committed, it is time to trigger the automation pipeline. Commit a change to your main branch and push it to your private Gitea server.
Navigate to the Actions tab of your repository. You will see a live execution log showing the runner picking up the job, checking out the codebase, logging into ghcr.io via the provided secrets, executing the Docker compilation, and pushing the layers to GitHub.
Once completed, visit your GitHub profile under the Packages section to confirm that your newly packaged container image is present and versioned accurately.
---Conclusion
By integrating Gitea Actions with GitHub Container Registry directly from your private VPS, you construct a highly optimized, cost-effective, and secure hybrid CI/CD pipeline. This implementation keeps your primary code development workflows local and proprietary, while effortlessly offloading global package distribution tasks to GitHub's infrastructure. As your infrastructure requirements grow, this modular configuration allows you to scale up additional runners across multiple servers effortlessly, ensuring sustainable, professional DevOps management.
