1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# https://docs.gitea.com/installation/install-with-docker#sshing-shim-with-authorized_keys

- name: Set up Gitea
  hosts: lotus-land-story
  vars:
    version: "{{ versions.gitea }}"
    anubis_version: "{{ versions.anubis }}"
  tasks:

    - name: Create git user
      ansible.builtin.user:
        name: git
        create_home: true
      register: git_user

    - name: Create ssh key
      community.crypto.openssh_keypair:
        path: "{{ git_user.home }}/.ssh/id_ecdsa"
        type: ecdsa
        owner: "{{ git_user.name }}"
        group: "{{ git_user.group }}"
      register: ssh_key

    - name: Set authorized key
      ansible.posix.authorized_key:
        user: "{{ git_user.name }}"
        state: present
        key: "{{ ssh_key.public_key }}"

    - name: Make /usr/local/bin/gitea
      ansible.builtin.copy:
        dest: /usr/local/bin/gitea
        content: |
          #!/bin/sh
          ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
        mode: "0755"

    - name: Make /mnt/lotus-land-story/gitea
      ansible.builtin.file:
        path: /mnt/lotus-land-story/gitea
        state: directory
        mode: "0755"
        owner: "{{ git_user.uid }}"
        group: "{{ git_user.group }}"

    - name: Run Anubis
      tags: anubis
      community.docker.docker_container:
        name: anubis
        image: ghcr.io/techarohq/anubis:{{ anubis_version }}
        restart: true
        env:
          COOKIE_DOMAIN: kejadlen.dev
          OG_PASSTHROUGH: "true"
          SERVE_ROBOTS_TXT: "true"
          TARGET: http://gitea:3000
        volumes:
        ports:
        restart_policy: unless-stopped
        networks:
          - name: lotus_land_story

    # TODO back this up using restic
    - name: Back up gitea if needed
      block:
        - name: Get current version
          ansible.builtin.command: >
            docker inspect
            --format '{{ '{{' }} index .Config.Labels "org.opencontainers.image.version"}}'
            gitea
          register: gitea_version
          changed_when: false

        - name: Stop and backup gitea
          when: gitea_version.stdout | trim != version
          block:
            - name: Stop gitea
              community.docker.docker_container:
                name: gitea
                state: stopped
            - name: Backup db
              ansible.builtin.copy:
                src: /mnt/lotus-land-story/gitea/gitea/gitea.db
                dest: /mnt/lotus-land-story/gitea/gitea/gitea.db.bak
                mode: "0400"
                remote_src: true

    - name: Run Gitea
      community.docker.docker_container:
        name: gitea
        image: docker.gitea.com/gitea:{{ version }}
        restart: true
        env:
          USER_UID: "{{ git_user.uid | string }}"
          USER_GID: "{{ git_user.group | string }}"
          GITEA__mailer__PASSWD: "{{ gitea.mailer_password }}"
          GITEA__metrics__TOKEN: "{{ gitea.metrics.token }}"
        volumes:
          - /mnt/lotus-land-story/gitea:/data
          - /etc/timezone:/etc/timezone:ro
          - /etc/localtime:/etc/localtime:ro
          - /home/git/.ssh/:/data/git/.ssh
        ports:
          - "2222:22"
        restart_policy: unless-stopped
        networks:
          - name: lotus_land_story
      no_log: true

  handlers:
    - name: Import restarts
      ansible.builtin.import_tasks: restarts.yml

# The runner delegates job containers to the host docker daemon (via the
# mounted socket) rather than a DinD sidecar. DinD gives each job its own
# isolated daemon, so job containers land on dind's internal bridge and
# can't resolve `gitea` on the lotus_land_story network — checkout fails.
# Mounting the host socket plus `container.network` in config.yaml puts
# job containers on lotus_land_story alongside gitea.
- name: Set up Gitea Actions runner
  hosts: lotus-land-story
  tags: gitea-runner
  vars:
    runner_version: "{{ versions.gitea_runner }}"
  tasks:

    - name: Make /mnt/lotus-land-story/gitea-runner
      ansible.builtin.file:
        path: /mnt/lotus-land-story/gitea-runner
        state: directory
        mode: "0755"

    - name: Write Gitea Actions runner config
      ansible.builtin.copy:
        dest: /mnt/lotus-land-story/gitea-runner/config.yaml
        mode: "0644"
        content: |
          container:
            network: lotus_land_story

    - name: Run Gitea Actions runner
      community.docker.docker_container:
        name: gitea-runner
        image: gitea/act_runner:{{ runner_version }}
        env:
          CONFIG_FILE: /data/config.yaml
          GITEA_INSTANCE_URL: http://gitea:3000
          GITEA_RUNNER_REGISTRATION_TOKEN: "{{ gitea.runner_registration_token }}"
        volumes:
          - /mnt/lotus-land-story/gitea-runner:/data
          - /var/run/docker.sock:/var/run/docker.sock
        restart_policy: unless-stopped
        networks:
          - name: lotus_land_story
      no_log: true

# vim: ft=yaml.ansible