diff --git a/roles/forgejo/handlers/main.yml b/roles/forgejo/handlers/main.yml new file mode 100644 index 0000000..e598141 --- /dev/null +++ b/roles/forgejo/handlers/main.yml @@ -0,0 +1,23 @@ +- name: reload nginx + service: + name: nginx + state: reloaded + when: '"handler" not in ansible_skip_tags' + +- name: restart forgejo + service: + name: forgejo + state: restarted + notify: wait for forgejo + when: '"handler" not in ansible_skip_tags' + +- name: restart forgejo-runner + service: + name: forgejo-runner + state: restarted + when: '"handler" not in ansible_skip_tags' + +- name: wait for forgejo + wait_for: + host: localhost + port: 3000 diff --git a/roles/forgejo/tasks/main.yml b/roles/forgejo/tasks/main.yml new file mode 100644 index 0000000..90cb159 --- /dev/null +++ b/roles/forgejo/tasks/main.yml @@ -0,0 +1,170 @@ +- name: Add testing repo + lineinfile: + path: /etc/apk/repositories + line: '@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing' + notify: update package cache + register: repo + +- name: Install forgejo + package: + update_cache: '{{ repo.changed }}' + name: + - forgejo@testing + - forgejo-runner@testing + - podman + +- name: Enable forgejo service + service: + name: forgejo + state: started + enabled: yes + +- name: Create nginx site + template: + dest: /etc/nginx/http.d/forgejo.conf + src: forgejo.conf.j2 + notify: reload nginx + +- meta: flush_handlers + +- name: Get passwords + set_fact: + password: '{{ lookup("passwordstore", "vm/"~inventory_hostname, returnall=true) | from_yaml }}' + +- name: Post installation data + uri: + creates: /var/lib/forgejo/db/forgejo.db + url: 'https://{{ fqdns | first }}' + method: POST + body_format: form-urlencoded + body: + - [ db_type, sqlite3 ] + - [ db_path, /var/lib/forgejo/db/forgejo.db ] + - [ app_name, 'FRI git' ] + - [ repo_root_path, /var/lib/forgejo/git ] + - [ lfs_root_path, /var/lib/forgejo/data/lfs ] + - [ run_user, forgejo ] + - [ http_port, 3000 ] + - [ ssh_port, 22 ] + - [ domain, '{{ fqdns | first }}' ] + - [ app_url, 'https://{{ fqdns | first }}/' ] + - [ log_root_path, /var/lib/forgejo/log ] + - [ allow_only_external_registration, on ] + - [ default_allow_create_organization, on ] + - [ default_enable_timetracking, on ] + - [ enable_open_id_sign_up, on ] + - [ offline_mode, on ] + - [ disable_gravatar, on ] + - [ admin_name, '{{ password.admin_user }}' ] + - [ admin_email, '{{ password.admin_mail }}' ] + - [ admin_passwd, '{{ password.admin_pass }}' ] + - [ admin_confirm_passwd, '{{ password.admin_pass }}' ] + #- [ no_reply_address, noreply.localhost ] + +- name: Configure forgejo + ini_file: + path: /etc/forgejo/app.ini + section: '{{ item.section }}' + option: '{{ item.option }}' + value: '{{ item.value }}' + loop: + - section: repository + option: DEFAULT_BRANCH + value: master + - section: repository + option: ENABLE_PUSH_CREATE_ORG + value: true + - section: repository + option: ENABLE_PUSH_CREATE_USER + value: true + notify: restart forgejo + +- name: Set up SSO + become: yes + become_method: su + become_user: forgejo + command: | + forgejo admin auth add-oauth --provider=openidConnect \ + --name '{{ password.oidc_name }}' + --auto-discover-url '{{ password.oidc_endpoint }}' + --key '{{ password.oidc_client_id }}' + --secret '{{ password.oidc_client_secret }}' + register: result + changed_when: + - result.rc == 0 + failed_when: + # task fails when both are true + - result.rc != 0 + - '"login source already exists" not in result.stderr' + +- name: Get forgejo-runner user + user: + name: forgejo-runner + register: user_info + +- name: Configure subuid + lineinfile: + path: /etc/subuid + line: '{{ user_info.name }}:{{ user_info.uid }}00000:65536' + regexp: '^{{ user_info.name }}:' + +- name: Configure subgid + lineinfile: + path: /etc/subgid + line: '{{ user_info.name }}:{{ user_info.group }}00000:65536' + regexp: '^{{ user_info.name }}:' + +- name: Create podman service for forgejo-runner + file: + path: /etc/init.d/podman.forgejo-runner + src: podman + state: link + +- name: Configure podman service for forgejo-runner + copy: + dest: /etc/conf.d/podman.forgejo-runner + content: podman_user="forgejo-runner" + +- name: Configure forgejo-runner + template: + dest: /etc/forgejo-runner/config.yaml + src: config.yaml.j2 + owner: forgejo-runner + group: forgejo-runner + mode: 0600 + notify: restart forgejo-runner + +- name: Check runner registration + stat: + path: /var/lib/forgejo-runner/.runner + register: runner_config + +- name: Register runner + when: not runner_config.stat.exists + notify: restart forgejo-runner + block: + - name: Get runner token + become: yes + become_method: su + become_user: forgejo + command: forgejo actions generate-runner-token + register: token + + - name: Register runner + become: yes + become_method: su + become_user: forgejo-runner + become_flags: '-s /bin/sh -l' + command: | + forgejo-runner register --no-interactive --name runner + --instance https://git.fri.uni-lj.si + --token '{{ token.stdout }}' + +- name: Enable forgejo-runner services + service: + name: '{{ item }}' + state: started + enabled: yes + loop: + - forgejo-runner + - podman.forgejo-runner diff --git a/roles/forgejo/templates/config.yaml.j2 b/roles/forgejo/templates/config.yaml.j2 new file mode 100644 index 0000000..b0aac31 --- /dev/null +++ b/roles/forgejo/templates/config.yaml.j2 @@ -0,0 +1,63 @@ +# TODO remove what’s not needed and properly configure the rest + +log: + level: debug + +runner: + file: .runner + env_file: .env + insecure: false + # The labels of a runner are used to determine which jobs the runner can run, and how to run them. + # Like: ["macos-arm64:host", "ubuntu-latest:docker://node:16-bullseye", "ubuntu-22.04:docker://node:16-bullseye"] + # If it's empty when registering, it will ask for inputting labels. + # If it's empty when execute `deamon`, will use labels in `.runner` file. + labels: [] + +#cache: +# # The host of the cache server. +# # It's not for the address to listen, but the address to connect from job containers. +# # So 0.0.0.0 is a bad choice, leave it empty to detect automatically. +# host: "" +# # The port of the cache server. +# # 0 means to use a random available port. +# port: 0 +# # The external cache server URL. Valid only when enable is true. +# # If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself. +# # The URL should generally end with "/". +# external_server: "" + +container: + # Specifies the network to which the container will connect. + # Could be host, bridge or the name of a custom network. + # If it's empty, create a network automatically. + network: "host" + # Whether to create networks with IPv6 enabled. Requires the Docker daemon to be set up accordingly. + # Only takes effect if "network" is set to "". + enable_ipv6: true + # And other options to be used when the container is started (eg, --add-host=my.forgejo.url:host-gateway). + options: + # The parent directory of a job's working directory. + # If it's empty, /workspace will be used. + workdir_parent: + # Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob + # You can specify multiple volumes. If the sequence is empty, no volumes can be mounted. + # For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to: + # valid_volumes: + # - data + # - /src/*.json + # If you want to allow any volume, please use the following configuration: + # valid_volumes: + # - '**' + valid_volumes: [] + # overrides the docker client host with the specified one. + # If it's empty, act_runner will find an available docker host automatically. + # If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers. + # If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work. + docker_host: "unix:///tmp/podman-run-{{ user_info.uid }}/podman/podman.sock" + # Pull docker image(s) even if already present + force_pull: false + +host: + # The parent directory of a job's working directory. + # If it's empty, $HOME/.cache/act/ will be used. + workdir_parent: diff --git a/roles/forgejo/templates/forgejo.conf.j2 b/roles/forgejo/templates/forgejo.conf.j2 new file mode 100644 index 0000000..c835c25 --- /dev/null +++ b/roles/forgejo/templates/forgejo.conf.j2 @@ -0,0 +1,23 @@ +{% for fqdn in fqdns %} +server { + server_name {{ fqdn }}; + + listen [::]:443 ssl ipv6only=off; + ssl_certificate /etc/letsencrypt/live/{{ fqdn }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ fqdn }}/privkey.pem; + + location / { + proxy_pass http://127.0.0.1:3000; + + proxy_set_header Connection $http_connection; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + client_max_body_size 512M; + } +} + +{% endfor %} diff --git a/setup.yml b/setup.yml index 2d5b235..139584b 100644 --- a/setup.yml +++ b/setup.yml @@ -31,3 +31,9 @@ roles: - debian - samba + +- hosts: git + roles: + - alpine + - nginx + - forgejo