Fedora - Home Server (Git Server)

Our Home Server is doing some nice stuff already. With the last articles, I want to demonstrate how you can deploy some useful applications on it. Running your own Git server has some advantages, when it comes to private work or testing.

Fedora - Home Server (Git Server)
Photo by Yancy Min / Unsplash

Our Home Server is doing some nice stuff already. With the last articles, I want to demonstrate how you can deploy some useful applications on it. Running your own Git server has some advantages, when it comes to private work or testing.

If you don't know anything about Git, I recommend having a look at the articles "Git - Getting Started" and "Git - Next Steps" beforehand.

Enough of the intro stuff, let's directly dig into the deployment.

Intro

This series is explaining how we are setting up a home server from scratch. You can find links to the previous articles below.

  1. Intro & Concept
  2. Hardware & OS
  3. Automation
  4. Management
  5. Virtualization
  6. Container
  7. Time, DHCP, DNS Server
  8. Git Server
  9. File, Calendar, Contact Sync
  10. Application Dashboard

This time, we will our own Git server. Shall we?

Gitea

Gitea is an Open Source Git server, that provides a pleasant web UI and lots of functionality, you might know from GitHub. Compared to GitLab, it is way easier to deploy and maintain. I am running my own instance for over 2 years now, with zero outages.

Gitea

If you are looking for an internet hosted Gitea instance, you can find it on codeberg.org.

Gitea with Ansible and Podman

In the past articles, we were getting used to Podman deployments with Ansible already. We will do the same pattern with Gitea. You will need Ansible on your workstation and Podman on your home server.

The code

We will create a new playbook deploy_gitea_container.yml as shown below.

---
# ansible/playbooks/deploy_gitea_container.yml

- name: "Deploy gitea Container"
  hosts: "all"

  vars:
    gitea_publish_http: "3000"
    gitea_publish_ssh: "2222"

    gitea_net_name: "gitea"

    ## Database Management

    gitea_db_image_name: "docker.io/library/mariadb"
    gitea_db_image_tag: "10"
    gitea_db_image_auto_update: true

    gitea_db_name: "gitea"
    gitea_db_user: "gitea"
    gitea_db_pass: "password"

    ## App Management

    gitea_app_image_name: "docker.io/gitea/gitea"
    gitea_app_image_tag: "1"
    gitea_app_image_auto_update: true

  tasks:

    # Network

    - name: "Create gitea Podman Network"
      containers.podman.podman_network:
        name: "{{ gitea_net_name }}"
        state: "present"
      become: true

    ## Database

    - name: "Pull gitea-db Image"
      containers.podman.podman_image:
        name: "{{ gitea_db_image_name }}"
        tag: "{{ gitea_db_image_tag }}"
        state: "present"
      become: true

    - name: "Create gitea-db Service File"
      ansible.builtin.template:
        src: "container-gitea-db.service.j2"
        dest: "/etc/systemd/system/container-gitea-db.service"
        owner: "root"
        group: "root"
        mode: 0644
      become: true

    - name: "Start & Enable gitea-db Service"
      ansible.builtin.systemd:
        name: "container-gitea-db.service"
        state: "started"
        enabled: true
        daemon_reload: true
      become: true

    ## Application

    - name: "Pull gitea-app Image"
      containers.podman.podman_image:
        name: "{{ gitea_app_image_name }}"
        tag: "{{ gitea_app_image_tag }}"
        state: "present"
      become: true

    - name: "Create gitea-app Service File"
      ansible.builtin.template:
        src: "container-gitea-app.service.j2"
        dest: "/etc/systemd/system/container-gitea-app.service"
        owner: "root"
        group: "root"
        mode: 0644
      become: true

    - name: "Start & Enable gitea-app Service"
      ansible.builtin.systemd:
        name: "container-gitea-app.service"
        state: "started"
        enabled: true
        daemon_reload: true
      become: true
...
ansible/playbooks/deploy_gitea_container.yml

This playbook looks very similar to the ones we used beforehand in "Fedora - Home Server (Time, DHCP, DNS Server 1/2)" and "Fedora - Home Server (Time, DHCP, DNS Server 2/2)". There are more tasks, though. Gitea requires a database, which is part of this new playbook. Ensure that you set the password to your desired one in the vars: section.

If you haven't used Ansible with Podman already, you also should ensure that a requirements.yml file is existing.

---
# ansible/requirements.yml

collections:

  - name: "ansible.posix"
  - name: "community.general"
  - name: "community.libvirt"
  - name: "containers.podman"
...
ansible/requirements.yml

The above playbook also creates two systemd service files from template files. This will ensure that our containers can be handled as described in "Podman - systemd container management" and "Podman - Auto Updates".

Let's create one for the Gitea app server.

[Unit]
Description=Podman container-gitea-app.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
Type=notify
NotifyAccess=all

ExecStartPre=/bin/rm -f %t/%n.ctr-id

ExecStart=/usr/bin/podman run \
	--cidfile=%t/%n.ctr-id \
	--cgroups=no-conmon \
	--rm \
	--sdnotify=conmon \
	--replace \
	--publish {{ gitea_publish_http }}:3000/tcp \
	--publish {{ gitea_publish_ssh }}:2222/tcp \
	--detach \
	--tty \
	--label "io.containers.autoupdate=registry" \
	--volume gitea-app-data:/data/:Z \
	--volume gitea-app-conf:/etc/gitea/:Z \
	--network=gitea \
	--env GITEA__database__NAME={{ gitea_db_name }} \
	--env GITEA__database__USER={{ gitea_db_user }} \
	--env GITEA__database__PASSWD={{ gitea_db_pass }} \
	--env GITEA__database__DB_TYPE=mysql \
	--env GITEA__database__HOST=gitea-db:3306 \
	--env GITEA__service__DISABLE_REGISTRATION=true \
	--name=gitea-app \
	{{ gitea_app_image_name }}:{{ gitea_app_image_tag }}

ExecStop=/usr/bin/podman stop \
	--ignore \
	--cidfile=%t/%n.ctr-id

ExecStopPost=/usr/bin/podman rm \
	--force \
	--ignore \
	--cidfile=%t/%n.ctr-id

[Install]
WantedBy=default.target
ansible/playbooks/templates/container-gitea-app.service.j2

And another one for the Gitea DB server.

[Unit]
Description=Podman container-gitea-db.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
Type=notify
NotifyAccess=all

ExecStartPre=/bin/rm -f %t/%n.ctr-id

ExecStart=/usr/bin/podman run \
	--cidfile=%t/%n.ctr-id \
	--cgroups=no-conmon \
	--rm \
	--sdnotify=conmon \
	--replace \
	--detach \
	--tty \
	--label "io.containers.autoupdate=registry" \
	--volume gitea-db:/var/lib/mysql/:Z \
	--network=gitea \
	--env MARIADB_RANDOM_ROOT_PASSWORD=true \
	--env MARIADB_DATABASE={{ gitea_db_name }} \
	--env MARIADB_USER={{ gitea_db_user }} \
	--env MARIADB_PASSWORD={{ gitea_db_pass }} \
	--name=gitea-db \
	{{ gitea_db_image_name }}:{{ gitea_db_image_tag }}

ExecStop=/usr/bin/podman stop \
	--ignore \
	--cidfile=%t/%n.ctr-id

ExecStopPost=/usr/bin/podman rm \
	--force --ignore \
	--cidfile=%t/%n.ctr-id

[Install]
WantedBy=default.target
ansible/playbooks/templates/container-gitea-db.service.j2

As always, you can find the above code in the home server repository.

GitHub - dschier-wtd/fedora-homeserver: Kickstart and Ansible setup of my homeserver.
Kickstart and Ansible setup of my homeserver. Contribute to dschier-wtd/fedora-homeserver development by creating an account on GitHub.

How it works

The playbook will create a new Podman network first. To ensure that the images are present, we will download them as a separate task. We are also creating two systemd services, which will start the containers. The service files also allow auto-updates of the container images via the podman-auto-update service.

Run the playbook

To install Gitea on your home server, you just need to execute the playbook.

# Run the playbook
$ ansible-playbook -i IP_ADDRESS, -u USER -k -K ansible/playbooks/deploy_gitea_container.yml

At the end of the run, you might see an output similar to the below.

PLAY RECAP ***********************************************************************************************************************************************************************
192.168.124.100                  : ok=8    changed=7    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

You can check the deployment with the below commands.

# Check if the db service is running
$ sudo systemctl status container-gitea-db.service

# Check if the app service is running
$ sudo systemctl status container-gitea-app.service

# Check if the containers are running
$ sudo podman ps

If everything is working, point your browser to your home server on port 3000 http://IP_ADDRESS:3000. You will be greeted with the setup wizard.

Screenshot - Gitea Setup Wizard

At the very end, you can find a section "Administrator Account Settings". Enter your desired credentials for the admin account there. Afterwards, hit the "Install Gitea" button. After some time (maybe a reload of the page), you will land on your fresh installed Gitea server.

Screenshot - Gitea Initial Login

One more thing

We deployed the MariaDB container with a random root password. To fetch and save this, you need to perform the below command.

# Read logs from gitea db
$ sudo podman logs gitea-db

In the output, you will find a line, that looks similar to the below.

2022-12-14 20:07:41+00:00 [Note] [Entrypoint]: GENERATED ROOT PASSWORD: M`dF}RznoWnu,hn,]+w><>_>0gz{LVFD

Save this password in a secure location, in case you need it.

Gitea can be a beast, so let me provide some documentation. I also want to provide the newly created "whiletruedoio.container" collection, that also holds a role to deploy Gitea as Podman container.

Documentation - Docs
Installation with Docker - Docs
GitHub - whiletruedoio/whiletruedoio.container: Ansible collection to provide container setups and prepared container deployments.
Ansible collection to provide container setups and prepared container deployments. - GitHub - whiletruedoio/whiletruedoio.container: Ansible collection to provide container setups and prepared cont...

Conclusion

That sums up our Git server deployment. I hope this helps to get a good understanding how these things can be handled. Also, having your own git server in a local network can be a good solution for temporary work, experiments, and stuff that is not ready for the public.

Do you have a local Git server? Which one is your favorite?