From 5434804fa11ca13a81d9e5aaef88c30789464436 Mon Sep 17 00:00:00 2001 From: Dave Gallant Date: Sat, 9 Dec 2023 23:56:50 -0500 Subject: [PATCH] Add ""Setting Up Gitea Actions With Tailscale"" --- ...setting-up-gitea-actions-with-tailscale.md | 202 ++++++++++++ public/about/index.html | 1 + .../16/appgate-sdp-on-arch-linux/index.html | 1 + .../06/what-to-do-with-a-homelab/index.html | 1 + .../08/why-i-threw-out-my-dotfiles/index.html | 1 + .../index.html | 1 + .../index.html | 2 + .../running-k3s-in-lxc-on-proxmox/index.html | 1 + .../backing-up-gmail-with-synology/index.html | 1 + .../index.html | 1 + .../10/watching-youtube-in-private/index.html | 1 + .../index.html | 1 + .../index.html | 307 ++++++++++++++++++ public/categories/index.html | 1 + public/categories/index.xml | 3 +- .../gitea-runners.png | Bin 0 -> 36278 bytes public/index.html | 34 +- public/index.xml | 34 +- public/page/2/index.html | 160 +++++++++ public/page/index.html | 1 + public/page/index.xml | 5 +- public/page/search/index.html | 1 + public/post/index.html | 3 + public/post/index.xml | 30 +- public/sitemap.xml | 36 +- public/tags/adguard/index.html | 1 + public/tags/adguard/index.xml | 5 +- public/tags/aks/index.html | 1 + public/tags/aks/index.xml | 5 +- public/tags/aws-vault/index.html | 1 + public/tags/aws-vault/index.xml | 5 +- public/tags/aws/index.html | 1 + public/tags/aws/index.xml | 7 +- public/tags/azure/index.html | 1 + public/tags/azure/index.xml | 5 +- public/tags/backup/index.html | 1 + public/tags/backup/index.xml | 5 +- public/tags/bastion/index.html | 1 + public/tags/bastion/index.xml | 5 +- public/tags/cloud-sql-proxy/index.html | 1 + public/tags/cloud-sql-proxy/index.xml | 5 +- public/tags/containers/index.html | 1 + public/tags/containers/index.xml | 5 +- public/tags/database/index.html | 1 + public/tags/database/index.xml | 5 +- public/tags/degoogle/index.html | 1 + public/tags/degoogle/index.xml | 7 +- public/tags/docker/index.html | 1 + public/tags/docker/index.xml | 5 +- public/tags/dotfiles/index.html | 1 + public/tags/dotfiles/index.xml | 5 +- public/tags/eks/index.html | 1 + public/tags/eks/index.xml | 5 +- public/tags/gitea-actions/index.html | 151 +++++++++ public/tags/gitea-actions/index.xml | 20 ++ public/tags/gitea/index.html | 151 +++++++++ public/tags/gitea/index.xml | 20 ++ public/tags/github-actions/index.html | 151 +++++++++ public/tags/github-actions/index.xml | 20 ++ public/tags/gmail/index.html | 1 + public/tags/gmail/index.xml | 5 +- public/tags/grafana/index.html | 1 + public/tags/grafana/index.xml | 5 +- public/tags/home-manager/index.html | 1 + public/tags/home-manager/index.xml | 5 +- public/tags/homelab/index.html | 1 + public/tags/homelab/index.xml | 5 +- public/tags/index.html | 21 +- public/tags/index.xml | 134 ++------ public/tags/invidious/index.html | 1 + public/tags/invidious/index.xml | 5 +- public/tags/jellyfin/index.html | 1 + public/tags/jellyfin/index.xml | 5 +- public/tags/k3s/index.html | 1 + public/tags/k3s/index.xml | 5 +- public/tags/k8s/index.html | 1 + public/tags/k8s/index.xml | 5 +- .../kubectl-plugin-socks5-proxy/index.html | 1 + .../kubectl-plugin-socks5-proxy/index.xml | 5 +- public/tags/linux/index.html | 1 + public/tags/linux/index.xml | 5 +- public/tags/lxc/index.html | 1 + public/tags/lxc/index.xml | 5 +- public/tags/netdata/index.html | 1 + public/tags/netdata/index.xml | 5 +- public/tags/nix/index.html | 1 + public/tags/nix/index.xml | 5 +- public/tags/openwrt/index.html | 1 + public/tags/openwrt/index.xml | 5 +- public/tags/pfsense/index.html | 1 + public/tags/pfsense/index.xml | 5 +- public/tags/pihole/index.html | 1 + public/tags/pihole/index.xml | 5 +- public/tags/plex/index.html | 1 + public/tags/plex/index.xml | 5 +- public/tags/podman/index.html | 1 + public/tags/podman/index.xml | 5 +- public/tags/privacy/index.html | 1 + public/tags/privacy/index.xml | 5 +- public/tags/proxmox/index.html | 1 + public/tags/proxmox/index.xml | 7 +- public/tags/proxy/index.html | 1 + public/tags/proxy/index.xml | 5 +- public/tags/python/index.html | 1 + public/tags/python/index.xml | 7 +- public/tags/ransomware/index.html | 1 + public/tags/ransomware/index.xml | 5 +- public/tags/router-on-a-stick/index.html | 1 + public/tags/router-on-a-stick/index.xml | 5 +- public/tags/router/index.html | 1 + public/tags/router/index.xml | 5 +- public/tags/security/index.html | 1 + public/tags/security/index.xml | 5 +- public/tags/socks/index.html | 1 + public/tags/socks/index.xml | 5 +- public/tags/synology/index.html | 1 + public/tags/synology/index.xml | 5 +- public/tags/tailscale/index.html | 3 + public/tags/tailscale/index.xml | 14 +- public/tags/virtualization/index.html | 1 + public/tags/virtualization/index.xml | 5 +- public/tags/vlan/index.html | 1 + public/tags/vlan/index.xml | 5 +- public/tags/vpn/index.html | 1 + public/tags/vpn/index.xml | 5 +- public/tags/yewtu.be/index.html | 1 + public/tags/yewtu.be/index.xml | 5 +- public/tags/youtube/index.html | 1 + public/tags/youtube/index.xml | 5 +- .../gitea-runners.png | Bin 0 -> 36278 bytes 130 files changed, 1469 insertions(+), 335 deletions(-) create mode 100644 content/post/setting-up-gitea-actions-with-tailscale.md create mode 100644 public/blog/2023/12/10/setting-up-gitea-actions-with-tailscale/index.html create mode 100644 public/images/setting-up-gitea-actions-with-tailscale/gitea-runners.png create mode 100644 public/page/2/index.html create mode 100644 public/tags/gitea-actions/index.html create mode 100644 public/tags/gitea-actions/index.xml create mode 100644 public/tags/gitea/index.html create mode 100644 public/tags/gitea/index.xml create mode 100644 public/tags/github-actions/index.html create mode 100644 public/tags/github-actions/index.xml create mode 100644 static/images/setting-up-gitea-actions-with-tailscale/gitea-runners.png diff --git a/content/post/setting-up-gitea-actions-with-tailscale.md b/content/post/setting-up-gitea-actions-with-tailscale.md new file mode 100644 index 00000000..7bf4760c --- /dev/null +++ b/content/post/setting-up-gitea-actions-with-tailscale.md @@ -0,0 +1,202 @@ +--- +title: "Setting Up Gitea Actions With Tailscale" +date: 2023-12-10T17:22:11-05:00 +lastmod: 2023-12-10T17:22:11-05:00 +draft: false +keywords: [] +description: "" +tags: ["gitea", "gitea actions", "github actions", "tailscale"] +categories: [] +author: "" + +# You can also close(false) or open(true) something for this content. +# P.S. comment can only be closed +comment: false +toc: false +autoCollapseToc: false +postMetaInFooter: false +hiddenFromHomePage: false +# You can also define another contentCopyright. e.g. contentCopyright: "This is another copyright." +contentCopyright: false +reward: false +mathjax: false +mathjaxEnableSingleDollar: false + +flowchartDiagrams: + enable: false + options: "" + +sequenceDiagrams: + enable: false + options: "" +--- + + + +In this post I'll go through the process of setting up Gitea Actions and [Tailscale](https://tailscale.com/), unlocking a simple and secure way to automate workflows. + +## What is Gitea? + +[Gitea](https://about.gitea.com/) is a lightweight and fast git server that has much of the same look and feel as github. I have been using it in my homelab to mirror repositories hosted on other platforms such as github and gitlab. These mirrors take advantage of the decentralized nature of git by serving as "backups". One of the main reasons I hadn't been using it more often was due to the lack of integrated CI/CD. This is no longer the case. + +## Gitea Actions + +[Gitea Actions](https://docs.gitea.com/usage/actions/overview) have made it into the [1.19.0 release](https://blog.gitea.com/release-of-1.19.0/). This feature had been in an experimental state up until [1.21.0](https://blog.gitea.com/release-of-1.21.0/) and is now enabled by default 🎉. + +So what are they? If you've ever used GitHub Actions (and if you're reading this, I imagine you have), they essentially allow you to run github workflows on gitea. Workflows between gitea and github are not completely interopable, but a lot of the same workflow syntax is already compatible on gitea. You can find a list of [unsupported workflows syntax](https://docs.gitea.com/usage/actions/comparison#unsupported-workflows-syntax). + +Actions work by using a [custom fork](https://gitea.com/gitea/act) of [nekos/act](https://github.com/nektos/act). Workflows run in a new container for every job. If you specify an action such as 'actions/checkout@v3', it defaults to downloading the scripts from github.com. To avoid internet egress, you could always clone the required actions to your local gitea instance. + +Actions (gitea's implementation) has me excited because it makes spinning up a network-isolated environment for workflow automation incredibly simple. + +## Integration with Tailscale + +So how does Tailscale help here? Well, more recently I've been exposing my self-hosted services through a combination of traefik and the tailscale (through the tailscale-traefik proxy integration described [here](https://traefik.io/blog/exploring-the-tailscale-traefik-proxy-integration/)). This allows for a nice looking dns name (i.e. gitea.my-tailnet-name.ts.net) and automatic tls certificate management. I can also share this tailscale node securely with other tailscale users without configuring any firewall rules on my router. + +## Deploying Gitea, Traefik, and Tailscale + +In my case, the following is already set up: + +- [docker-compose is installed](https://docs.docker.com/compose/install/linux/) +- [tailscale is installed on the gitea host](https://tailscale.com/kb/1017/install/) +- [tailscale magic dns is enabled](https://tailscale.com/kb/1081/magicdns/) + +My preferred approach to deploying code in a homelab environment is with docker compose. I have deployed this in a [proxmox lxc container](https://pve.proxmox.com/wiki/Linux_Container) based on debian with a hostname `gitea`. This could be deployed in any environment and with any hostname (as long you updated the tailscale machine name to your preferred subdomain for magic dns). + +The `docker-compose.yaml` file looks like: + +```yaml +version: "3.7" +services: + gitea: + image: gitea/gitea:1.21.1 + container_name: gitea + environment: + - USER_UID=1000 + - USER_GID=1000 + + - GITEA__server__DOMAIN=gitea.my-tailnet-name.ts.net + - GITEA__server__ROOT_URL=https://gitea.my-tailnet-name.ts.net + - GITEA__server__HTTP_ADDR=0.0.0.0 + - GITEA__server__LFS_JWT_SECRET=my-secret-jwt + restart: always + volumes: + - ./data:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + traefik: + image: traefik:v3.0.0-beta4 + container_name: traefik + security_opt: + - no-new-privileges:true + restart: unless-stopped + ports: + - 80:80 + - 443:443 + volumes: + - ./traefik/data/traefik.yaml:/traefik.yaml:ro + - ./traefik/data/dynamic.yaml:/dynamic.yaml:ro + - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock +``` + +`traefik/data/traefik.yaml`: + +```yaml +entryPoints: + https: + address: ":443" +providers: + file: + filename: dynamic.yaml +certificatesResolvers: + myresolver: + tailscale: {} +log: + level: INFO +``` + +and finally `traefik/data/dynamic/dynamic.yaml`: + +```yaml +http: + routers: + gitea: + rule: Host(`gitea.my-tailnet-name.ts.net`) + entrypoints: + - "https" + service: gitea + tls: + certResolver: myresolver + services: + gitea: + loadBalancer: + servers: + - url: "http://gitea:3000" +``` + +Something to consider is whether or not you want to use ssh with git. One method of getting this to work with containers is to use [ssh container passthrough](https://docs.gitea.com/installation/install-with-docker#ssh-container-passthrough). I decided to keep it simple and not use ssh, since communicating over https is perfectly fine for my use case. + +After adding the above configuration, running `docker compose up -d` should be enough to get your instance up and running. It will be accessible at [https://gitea.my-tailnet-name.ts.net](https://gitea.my-tailnet-name.ts.net) from within your tailnet. + +## Connecting a Runner + +I installed the runner by [following the docs](https://docs.gitea.com/usage/actions/quickstart#set-up-runner). I opted for installing it on a separate host (another lxc container) as recommended in the docs. I used the systemd unit file to ensure that the runner comes back online after system reboots. I installed tailscale on this act runner as well, so that it can have the same "networking privileges" as the main instance. + +After registering this runner and starting the daemon, it appeared in `/admin/actions/runners`: + +![image](/images/setting-up-gitea-actions-with-tailscale/gitea-runners.png) + +## Running a workflow + +Now it's time start running some automation. I used the [demo workflow](https://docs.gitea.com/usage/actions/quickstart#use-actions) as a starting point to verify that the runner is executing workflows. + +After this, I wanted to make sure that some of my existing workflows could be migrated over. + +The following workflow uses a matrix to run a job for several of my hosts using ansible playbooks that will do various tasks such as patching os updates and updating container images. + +```yaml +name: Run ansible playbooks +on: + push: + schedule: + - cron: "0 */12 * * *" + +jobs: + run-ansible-playbook: + runs-on: ubuntu-latest + strategy: + matrix: + host: + - changedetection + - grafana + - homer + - invidious + - jackett + - ladder + - miniflux + - plex + - qbittorrent + - tailscale-exit-node + - uptime-kuma + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Install ansible + run: | + apt update && apt install ansible -y + - name: Run playbook + uses: dawidd6/action-ansible-playbook@v2 + with: + playbook: playbooks/main.yml + requirements: requirements.yml + key: ${{ secrets.SSH_PRIVATE_KEY}} + options: | + --inventory inventory + --limit ${{ matrix.host }} +``` + +## Conclusion + +Gitea Actions are fast and the resource footprint is minimal. My gitea instance is currently using around 250mb of memory and a small fraction of a single cpu core (and the runner is using a similar amount of resources). This is impressive since many alternatives tend to require substantionally more resources (ahem, gitlab). It certainly doesn't hurt that the codebase is largely written in go. + +By combining gitea with the networking marvel that is tailscale, running workflows becomes simple and fun. Whether you are working on a team or working alone, this setup ensures that your workflows are securely accessible from anywhere with an internet connection. diff --git a/public/about/index.html b/public/about/index.html index 1593b854..a5c8960a 100644 --- a/public/about/index.html +++ b/public/about/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2020/03/16/appgate-sdp-on-arch-linux/index.html b/public/blog/2020/03/16/appgate-sdp-on-arch-linux/index.html index 614280f7..e27eccde 100644 --- a/public/blog/2020/03/16/appgate-sdp-on-arch-linux/index.html +++ b/public/blog/2020/03/16/appgate-sdp-on-arch-linux/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2021/09/06/what-to-do-with-a-homelab/index.html b/public/blog/2021/09/06/what-to-do-with-a-homelab/index.html index d7304095..2f5dde60 100644 --- a/public/blog/2021/09/06/what-to-do-with-a-homelab/index.html +++ b/public/blog/2021/09/06/what-to-do-with-a-homelab/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2021/09/08/why-i-threw-out-my-dotfiles/index.html b/public/blog/2021/09/08/why-i-threw-out-my-dotfiles/index.html index 24b6336b..b0c77e79 100644 --- a/public/blog/2021/09/08/why-i-threw-out-my-dotfiles/index.html +++ b/public/blog/2021/09/08/why-i-threw-out-my-dotfiles/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2021/09/17/automatically-rotating-aws-access-keys/index.html b/public/blog/2021/09/17/automatically-rotating-aws-access-keys/index.html index e25750a6..f7ded2a0 100644 --- a/public/blog/2021/09/17/automatically-rotating-aws-access-keys/index.html +++ b/public/blog/2021/09/17/automatically-rotating-aws-access-keys/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2021/10/11/replacing-docker-with-podman-on-macos-and-linux/index.html b/public/blog/2021/10/11/replacing-docker-with-podman-on-macos-and-linux/index.html index e3968b40..a5c0ae55 100644 --- a/public/blog/2021/10/11/replacing-docker-with-podman-on-macos-and-linux/index.html +++ b/public/blog/2021/10/11/replacing-docker-with-podman-on-macos-and-linux/index.html @@ -10,6 +10,7 @@ + @@ -105,6 +106,7 @@

...ignoring Docker updates is a paid feature now?? pic.twitter.com/ZxKW3b9LQM

— Brendan Dolan-Gavitt (@moyix) May 1, 2021
+

Docker has been one of the larger influencers in the container world, helping to standardize the OCI Image Format Specification. For many developers, containers have become synonymous with terms like docker and Dockerfile (a file containing build instructions for a container image). Docker has certainly made it very convenient to build and run containers, but it is not the only solution for doing so.

This post briefly describes my experience swapping out docker for podman on macOS.

What is a container?#

diff --git a/public/blog/2021/11/14/running-k3s-in-lxc-on-proxmox/index.html b/public/blog/2021/11/14/running-k3s-in-lxc-on-proxmox/index.html index 668b585f..005d2911 100644 --- a/public/blog/2021/11/14/running-k3s-in-lxc-on-proxmox/index.html +++ b/public/blog/2021/11/14/running-k3s-in-lxc-on-proxmox/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2022/03/13/backing-up-gmail-with-synology/index.html b/public/blog/2022/03/13/backing-up-gmail-with-synology/index.html index 466fba90..35b37a95 100644 --- a/public/blog/2022/03/13/backing-up-gmail-with-synology/index.html +++ b/public/blog/2022/03/13/backing-up-gmail-with-synology/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2022/04/02/virtualizing-my-router-with-pfsense/index.html b/public/blog/2022/04/02/virtualizing-my-router-with-pfsense/index.html index a0b14908..27da02e1 100644 --- a/public/blog/2022/04/02/virtualizing-my-router-with-pfsense/index.html +++ b/public/blog/2022/04/02/virtualizing-my-router-with-pfsense/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2022/12/10/watching-youtube-in-private/index.html b/public/blog/2022/12/10/watching-youtube-in-private/index.html index eb61ff51..6df09c53 100644 --- a/public/blog/2022/12/10/watching-youtube-in-private/index.html +++ b/public/blog/2022/12/10/watching-youtube-in-private/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2023/05/22/using-aks-and-socks-to-connect-to-a-private-azure-db/index.html b/public/blog/2023/05/22/using-aks-and-socks-to-connect-to-a-private-azure-db/index.html index d933a429..0f1826fd 100644 --- a/public/blog/2023/05/22/using-aks-and-socks-to-connect-to-a-private-azure-db/index.html +++ b/public/blog/2023/05/22/using-aks-and-socks-to-connect-to-a-private-azure-db/index.html @@ -10,6 +10,7 @@ + diff --git a/public/blog/2023/12/10/setting-up-gitea-actions-with-tailscale/index.html b/public/blog/2023/12/10/setting-up-gitea-actions-with-tailscale/index.html new file mode 100644 index 00000000..01a89a7b --- /dev/null +++ b/public/blog/2023/12/10/setting-up-gitea-actions-with-tailscale/index.html @@ -0,0 +1,307 @@ + + + + Setting Up Gitea Actions With Tailscale - davegallant + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+

Setting Up Gitea Actions With Tailscale

+
Posted on Dec 10, 2023
+
+ + +

In this post I’ll go through the process of setting up Gitea Actions and Tailscale, unlocking a simple and secure way to automate workflows.

+

What is Gitea?#

+

Gitea is a lightweight and fast git server that has much of the same look and feel as github. I have been using it in my homelab to mirror repositories hosted on other platforms such as github and gitlab. These mirrors take advantage of the decentralized nature of git by serving as “backups”. One of the main reasons I hadn’t been using it more often was due to the lack of integrated CI/CD. This is no longer the case.

+

Gitea Actions#

+

Gitea Actions have made it into the 1.19.0 release. This feature had been in an experimental state up until 1.21.0 and is now enabled by default 🎉.

+

So what are they? If you’ve ever used GitHub Actions (and if you’re reading this, I imagine you have), they essentially allow you to run github workflows on gitea. Workflows between gitea and github are not completely interopable, but a lot of the same workflow syntax is already compatible on gitea. You can find a list of unsupported workflows syntax.

+

Actions work by using a custom fork of nekos/act. Workflows run in a new container for every job. If you specify an action such as ‘actions/checkout@v3’, it defaults to downloading the scripts from github.com. To avoid internet egress, you could always clone the required actions to your local gitea instance.

+

Actions (gitea’s implementation) has me excited because it makes spinning up a network-isolated environment for workflow automation incredibly simple.

+

Integration with Tailscale#

+

So how does Tailscale help here? Well, more recently I’ve been exposing my self-hosted services through a combination of traefik and the tailscale (through the tailscale-traefik proxy integration described here). This allows for a nice looking dns name (i.e. gitea.my-tailnet-name.ts.net) and automatic tls certificate management. I can also share this tailscale node securely with other tailscale users without configuring any firewall rules on my router.

+

Deploying Gitea, Traefik, and Tailscale#

+

In my case, the following is already set up:

+ +

My preferred approach to deploying code in a homelab environment is with docker compose. I have deployed this in a proxmox lxc container based on debian with a hostname gitea. This could be deployed in any environment and with any hostname (as long you updated the tailscale machine name to your preferred subdomain for magic dns).

+

The docker-compose.yaml file looks like:

+
version: "3.7"
+services:
+  gitea:
+    image: gitea/gitea:1.21.1
+    container_name: gitea
+    environment:
+      - USER_UID=1000
+      - USER_GID=1000
+
+      - GITEA__server__DOMAIN=gitea.my-tailnet-name.ts.net
+      - GITEA__server__ROOT_URL=https://gitea.my-tailnet-name.ts.net
+      - GITEA__server__HTTP_ADDR=0.0.0.0
+      - GITEA__server__LFS_JWT_SECRET=my-secret-jwt
+    restart: always
+    volumes:
+      - ./data:/data
+      - /etc/timezone:/etc/timezone:ro
+      - /etc/localtime:/etc/localtime:ro
+  traefik:
+    image: traefik:v3.0.0-beta4
+    container_name: traefik
+    security_opt:
+      - no-new-privileges:true
+    restart: unless-stopped
+    ports:
+      - 80:80
+      - 443:443
+    volumes:
+      - ./traefik/data/traefik.yaml:/traefik.yaml:ro
+      - ./traefik/data/dynamic.yaml:/dynamic.yaml:ro
+      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
+
+

traefik/data/traefik.yaml:

+
entryPoints:
+  https:
+    address: ":443"
+providers:
+  file:
+    filename: dynamic.yaml
+certificatesResolvers:
+  myresolver:
+    tailscale: {}
+log:
+  level: INFO
+
+

and finally traefik/data/dynamic/dynamic.yaml:

+
http:
+  routers:
+    gitea:
+      rule: Host(`gitea.my-tailnet-name.ts.net`)
+      entrypoints:
+        - "https"
+      service: gitea
+      tls:
+        certResolver: myresolver
+  services:
+    gitea:
+      loadBalancer:
+        servers:
+          - url: "http://gitea:3000"
+
+

Something to consider is whether or not you want to use ssh with git. One method of getting this to work with containers is to use ssh container passthrough. I decided to keep it simple and not use ssh, since communicating over https is perfectly fine for my use case.

+

After adding the above configuration, running docker compose up -d should be enough to get your instance up and running. It will be accessible at https://gitea.my-tailnet-name.ts.net from within your tailnet.

+

Connecting a Runner#

+

I installed the runner by following the docs. I opted for installing it on a separate host (another lxc container) as recommended in the docs. I used the systemd unit file to ensure that the runner comes back online after system reboots. I installed tailscale on this act runner as well, so that it can have the same “networking privileges” as the main instance.

+

After registering this runner and starting the daemon, it appeared in /admin/actions/runners:

+

image

+

Running a workflow#

+

Now it’s time start running some automation. I used the demo workflow as a starting point to verify that the runner is executing workflows.

+

After this, I wanted to make sure that some of my existing workflows could be migrated over.

+

The following workflow uses a matrix to run a job for several of my hosts using ansible playbooks that will do various tasks such as patching os updates and updating container images.

+
name: Run ansible playbooks
+on:
+  push:
+  schedule:
+    - cron: "0 */12 * * *"
+
+jobs:
+  run-ansible-playbook:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        host:
+          - changedetection
+          - grafana
+          - homer
+          - invidious
+          - jackett
+          - ladder
+          - miniflux
+          - plex
+          - qbittorrent
+          - tailscale-exit-node
+          - uptime-kuma
+    steps:
+      - name: Check out repository code
+        uses: actions/checkout@v3
+      - name: Install ansible
+        run: |
+          apt update && apt install ansible -y
+      - name: Run playbook
+        uses: dawidd6/action-ansible-playbook@v2
+        with:
+          playbook: playbooks/main.yml
+          requirements: requirements.yml
+          key: ${{ secrets.SSH_PRIVATE_KEY}}
+          options: |
+            --inventory inventory
+            --limit ${{ matrix.host }}
+
+

Conclusion#

+

Gitea Actions are fast and the resource footprint is minimal. My gitea instance is currently using around 250mb of memory and a small fraction of a single cpu core (and the runner is using a similar amount of resources). This is impressive since many alternatives tend to require substantionally more resources (ahem, gitlab). It certainly doesn’t hurt that the codebase is largely written in go.

+

By combining gitea with the networking marvel that is tailscale, running workflows becomes simple and fun. Whether you are working on a team or working alone, this setup ensures that your workflows are securely accessible from anywhere with an internet connection.

+ + +
+
+ +
+
+
+
+
+
+
+ + + +
+ +
+ + + + + +
+ + diff --git a/public/categories/index.html b/public/categories/index.html index fdef0b4a..14191d36 100644 --- a/public/categories/index.html +++ b/public/categories/index.html @@ -9,6 +9,7 @@ + diff --git a/public/categories/index.xml b/public/categories/index.xml index 236e02c2..4be32f19 100644 --- a/public/categories/index.xml +++ b/public/categories/index.xml @@ -6,6 +6,7 @@ Recent content in Categories on davegallant Hugo -- gohugo.io en-us - Dave Gallant + Dave Gallant + diff --git a/public/images/setting-up-gitea-actions-with-tailscale/gitea-runners.png b/public/images/setting-up-gitea-actions-with-tailscale/gitea-runners.png new file mode 100644 index 0000000000000000000000000000000000000000..d733190d0485a4401948da71e04fa0cad5d7abd7 GIT binary patch literal 36278 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 P^4f$2#NXxeYkd13M@ip+ literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html index 1b43b6cc..1a0ff4ec 100644 --- a/public/index.html +++ b/public/index.html @@ -1,7 +1,7 @@ - + davegallant | Home @@ -11,6 +11,7 @@ + @@ -102,6 +103,16 @@ +
+

Setting Up Gitea Actions With Tailscale

+ +
+ + + +
+
+

Using AKS and SOCKS to connect to a Private Azure DB

@@ -189,21 +200,22 @@ - -
- -
-

AppGate SDP on Arch Linux

- -
- - -
+ +