Using a frontend project deployment as an example, this article will provide a step-by-step guide on how to create automated deployment workflows using Gitea actions. For those who don’t want to use Jenkins, Gitea actions is a good CI/CD
solution.
Introduction
After developing a project, we need to deploy it to a server so that users can access it. However, manual deployment for each update wastes time and energy. Therefore, we can use Gitea actions to create an automated workflow for quick project deployment.
What is Gitea Actions
Gitea actions is a feature of Gitea that allows us to create automated workflows for quick project deployment. Gitea actions can perform various tasks such as building, testing, and deploying. Gitea actions can use various programming languages and tools, such as Python, Java, Docker, etc. Additionally, Gitea actions is configured to be compatible with GitHub actions configuration as much as possible, so if you are already familiar with GitHub actions, you can also easily use Gitea actions. For more details, see the official documentation: Gitea actions
Preparation
Before we start creating this workflow, you need to prepare the following materials:
- A server, preferably with root privileges (for installing tools)
- A deployed Gitea repository, version at least >=
v1.19
, officially strongly recommended to usev1.20
or higher - Docker environment (not required, used on the host where the runner is deployed)
Note: The author has prepared: one build server + one deployment (target) server. You can use just one server, but be mindful of environment isolation.
Please ensure you have completed all preparations before proceeding with subsequent steps. For specific installation and configuration, please refer to the official documentation, which I won’t repeat here. Installation
If you use the 1panel panel, you can complete the installation with one click from the app store, which is what the author used.
Note: In versions <
v1.21.0
, you need to enable theactions
feature in the configuration file. Please refer to the official documentation Configuration. In later versions, it is enabled by default.
This tutorial uses Gitea version v1.22.6
!
Configuring Runner
In Gitea actions, running Jobs is done through Runners, so we need to configure a Runner first for our subsequent deployment workflow. There are two installation methods: you can install directly on the host or through a docker container. Here, the author will install through docker. To avoid excessive resource consumption, you can install it on a separate host (PS: For users in China, you can choose a Hong Kong server, which will make running jobs faster 😄). The author chose a Hong Kong VPS as the host.
Downloading act_Runner
First, we need to download this tool to register or generate configurations Download Link. Please select the version corresponding to your system on this page for download. After downloading, upload it to the server. Here, I uploaded it to the /gitea_runner2
directory on the server. You can also use tools like curl
to download directly. You can use the following command, but pay attention to the name and download link. My system is Debian12 x86_64
, so I downloaded act_runner-0.2.11-linux-amd64
.
curl -o act_runner2 https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64
After completion, set the execution permissions
chmod +x act_runner2 # Note the filename, please modify according to your actual situation
./act_runner --version # Seeing the version information means success
Generating Configuration
./act_runner2 generate-config > config.yaml
Generally, the default configuration is sufficient. If you have other requirements, please modify config.yaml
yourself.
Since the author chose to install via docker, if you choose to install directly on the host, you can skip the subsequent installation steps and refer to the official documentation for installation Direct Installation
Registering Runner
Here I choose to register through the docker-compose.yml
configuration method
Note: Modify the parameters in the configuration according to your own situation. The following configuration is for reference only!!!
version: "3.8"
services:
runner:
image: gitea/act_runner:latest
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: "<your_gitea.com>"
GITEA_RUNNER_REGISTRATION_TOKEN: "<your_registration_token_here>"
GITEA_RUNNER_NAME: "act_vps_runner2"
GITEA_RUNNER_LABELS: "act_vps_runner2"
volumes:
- /gitea_runner2/config.yaml:/config.yaml
- /gitea_runner2/runner_data/data:/data
- /gitea_runner2/runner_data/cache:/root/.cache
- /var/run/docker.sock:/var/run/docker.sock
Configuration Explanation
GITEA_RUNNER_REGISTRATION_TOKEN This parameter is the registration token, which needs to be obtained from your gitea. There are three levels in total. I directly chose the organization level, which can be obtained from the organization settings page, as shown in the following figure:
For other instance configuration pages and explanations, please refer to the official documentation, which has detailed explanations.
If you cannot see the settings page, please ensure that you have the correct permissions and that Actions is enabled. Check the Gitea version!!!
Running and Generating Runner
Since the author uses the 1panel panel, it can be directly orchestrated in the container options. If you don’t use this type of visualization tool, you need to manually execute docker-compose up -d
After success, you can check the container’s operation and logs. The logs will display the registration success information, as shown in the following figures:
Then we return to the page where you obtained the runner token, refresh it, and you should see your runner, as shown in the following figure:
The name in the figure is based on the name you set during registration configuration.
At this point, our runner deployment is complete, and we can now use it in projects.
Using Actions
The usage of gitea actions is similar to github actions. If you are not familiar with this type of configuration, you can first learn about github actions.
The author will use a vitepress
project as an example.
Creating Configuration Files
- Create a
.gitea/workflows
directory in the project root directory - Create a
deploy.yaml
configuration file in this directory - Let’s first write a test configuration to test environment variables, as shown below:
name: Deploy Test
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Print Environment Variables
run: env
- name: Print Current Directory
run: pwd
- name: List Files in Working Directory
run: ls -la
Then commit the code to the repository, and we should be able to see the execution task in the repository’s actions, as shown in the following figure:
PS: If you don’t see actions execution, or even don’t see the actions option, you may need to enable the actions option in the repository, organization, or management page
Configuring Build
We modify the deploy.yaml
configuration file to add build steps. I’m using pnpm here, please adjust some configurations according to your actual situation. I won’t elaborate too much here.
name: Deploy docs for project
run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
# TODO Temporary solution for https://github.com/go-gitea/gitea/issues/32481, waiting for gitea to release 1.23.0 for fix
- name: Install git
run: |
if ! command -v git &> /dev/null; then
apt-get update && apt-get install -y git
else
echo "git is already installed"
fi
- name: Checkout repository code
uses: https://gitea.com/actions/checkout@v4
with:
ref: 'main'
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
# Skip pnpm cache to reduce overhead
- name: Install pnpm
run: |
if ! command -v pnpm &> /dev/null; then
npm install -g pnpm@9
else
echo "pnpm is already installed"
fi
- name: Check Node.js and pnpm versions
run: |
echo "pnpm version ===>" && pnpm -v
echo "node version ===>" && node -v
# Simplify node_modules handling without caching
- name: Install dependencies
run: |
if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then
echo "Dependencies are outdated or missing, installing..."
pnpm install
else
echo "Dependencies are up-to-date, skipping installation."
fi
- name: Build docs
run: pnpm run docs:build
Special note: Installing git is to fix the current issue in gitea actions where code cannot be checked out through
actions/checkout
. This issue is expected to be fixed inv1.23.0
. Currently, we can only handle it this way. But from the author’s observation, it seems to be related to the image version used. If it’subuntu-latest
, you might not need to install it. Please base it on your actual situation.
If everything goes smoothly, you should see the build task completed in the workflow, as shown in the figure:
Deploying the Project
The principle of code deployment is actually to connect to the target server via ssh
and execute deployment scripts. Therefore, we need to configure SSH first, then use the actions
easingthemes/ssh-deploy to connect to the target server and push the code.
Configuring SSH
This step is actually to configure a user for the server and support SSH
login, which is password-free login. Therefore, we use the following commands in sequence on the target server. The author is using Debian 12
, please adjust the commands according to your actual situation!
Creating a User (It is recommended to create a user to operate the deployment directory, do not use the root user!!!)
sudo adduser deployuser # Please modify the username according to your actual situation
After successful creation, you can check if the /home/deployuser
directory exists. If it doesn’t exist, you may need to create it manually.
Creating Key Pairs
We need to first switch to the deployuser
user, then execute the following commands:
# 1. Create public and private keys
ssh-keygen -t rsa -b 4096 -C ""
# Add the public key content to the authorized_keys file
echo ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
# Set correct permissions
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
Granting Read and Write Permissions to Specific Directories (Can be skipped)
This requires a user with root
privileges to operate:
# 1. Create directory
mkdir -p /var/www/html/project
# 2. Modify directory permissions
sudo chown deployuser:deployuser /var/www/project
sudo chmod 700 /var/www/project
Since the author used 1panel
to manage websites, the directory is automatically generated, which differs from this, but the process steps are the same. Please modify according to your actual situation.
Configuring Key Information in Gitea
- In your gitea’s personal, organization, or management actions page, click
Secrets
, copy the private key we just generated on the server to theSecret
, and then clickAdd Secret
. - Since we will need the server IP and username later, it is also recommended to configure them in secrets or variables for later use.
Here, the author has configured the private key, server IP, and username in secrets, as shown in the figure:
At this point, we have completed the configuration required for deploying the project, and we can now start the deployment process.
PS: Since
easingthemes/ssh-deploy
needs to usersync
to execute script commands, this tool is required in both the image container and the target server. If it doesn’t exist, you need to install it in advance, especially on the target server. Generally, this needs to be done by a root user or a user with installation permissions.
Project Deployment
We add the following code to deploy.yml
, pay attention to the format!!!
- name: ssh deploy
uses: easingthemes/[email protected]
with:
SSH_PRIVATE_KEY: ${{ secrets.SH_SSH_PRIVATE_KEY }}
REMOTE_HOST: ${{ secrets.SH_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.SH_REMOTE_USER }}
SOURCE: "/.vitepress/dist/"
TARGET: "/1Panel/1panel/apps/openresty/openresty/www/sites/demo.zhaoguiyang.cn/index/dist" # Please modify to your deployment directory according to your actual situation
EXCLUDE: "/node_modules/"
If everything goes smoothly, you will see the actions executed successfully, and there will be a dist directory in your deployment directory, as shown in the following figures:
Next, you just need to use tools like nginx
to point to this directory, and it can be accessed.
PS: If you encounter errors in the above step, please carefully check the error logs. Based on the author’s experience, it’s most likely due to issues with SSH keys and permission handling. If you’re not using
ubuntu-latest
, you may also need to install some necessary tools according to the error messages, such asgit
,rsync
, etc.
Complete Configuration
name: Deploy docs for project
run-name: ${{ gitea.actor }} is building out Gitea Actions 🚀
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- name: Checkout repository code
uses: https://gitea.com/actions/checkout@v4
with:
ref: 'main'
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
# Skip pnpm cache to reduce overhead
- name: Install pnpm
run: |
if ! command -v pnpm &> /dev/null; then
npm install -g pnpm@9
else
echo "pnpm is already installed"
fi
- name: Check Node.js and pnpm versions
run: |
echo "pnpm version ===>" && pnpm -v
echo "node version ===>" && node -v
# Simplify node_modules handling without caching
- name: Install dependencies
run: |
if [ ! -d "node_modules" ] || [ "$(find package.json -newer node_modules)" ]; then
echo "Dependencies are outdated or missing, installing..."
pnpm install
else
echo "Dependencies are up-to-date, skipping installation."
fi
- name: Build docs
run: pnpm run docs:build
- name: ssh deploy
uses: easingthemes/[email protected]
with:
SSH_PRIVATE_KEY: ${{ secrets.SH_SSH_PRIVATE_KEY }}
REMOTE_HOST: ${{ secrets.SH_REMOTE_HOST }}
REMOTE_USER: ${{ secrets.SH_REMOTE_USER }}
SOURCE: "/.vitepress/dist/"
TARGET: "/1Panel/1panel/apps/openresty/openresty/www/sites/demo.zhaoguiyang.cn/index/dist" # Please modify to your deployment directory according to your actual situation
EXCLUDE: "/node_modules/"