From 300358fa98852ca0f1794153e7d2144704c3025b Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Tue, 7 Apr 2026 16:08:00 +0200 Subject: [PATCH] Set up Forgejo role and migrate Gitea to Forgejo 11 --- plays/emma.yml | 60 ++++++--- roles/any.software.forgejo-podman/README.md | 27 ++++ .../handlers/main.yml | 16 +++ .../any.software.forgejo-podman/meta/main.yml | 4 + .../tasks/main.yml | 55 ++++++++ .../templates/app.ini.j2 | 126 ++++++++++++++++++ .../templates/forgejo-app.container.j2 | 19 +++ .../templates/forgejo-postgres.container.j2 | 18 +++ .../templates/forgejo.Caddyfile.j2 | 5 + .../templates/forgejo.pod.j2 | 8 ++ 10 files changed, 319 insertions(+), 19 deletions(-) create mode 100644 roles/any.software.forgejo-podman/README.md create mode 100644 roles/any.software.forgejo-podman/handlers/main.yml create mode 100644 roles/any.software.forgejo-podman/meta/main.yml create mode 100644 roles/any.software.forgejo-podman/tasks/main.yml create mode 100644 roles/any.software.forgejo-podman/templates/app.ini.j2 create mode 100644 roles/any.software.forgejo-podman/templates/forgejo-app.container.j2 create mode 100644 roles/any.software.forgejo-podman/templates/forgejo-postgres.container.j2 create mode 100644 roles/any.software.forgejo-podman/templates/forgejo.Caddyfile.j2 create mode 100644 roles/any.software.forgejo-podman/templates/forgejo.pod.j2 diff --git a/plays/emma.yml b/plays/emma.yml index 1addce4..5c994a8 100644 --- a/plays/emma.yml +++ b/plays/emma.yml @@ -102,51 +102,73 @@ path: "{{ btrfs_raid.path }}/webdav/data" -- name: Set up Gitea +- name: Set up Forgejo hosts: emma - become: yes - tags: gitea + tags: forgejo roles: - role: any.common.btrfs-subvolumes + become: yes vars: subvolumes: # Data files and LFS are placed on RAID - filesystem_uuid: "{{ btrfs_raid.uuid }}" filesystem_path: "{{ btrfs_raid.path }}" - name: "/gitea/data" + name: "/forgejo/data" - filesystem_uuid: "{{ btrfs_raid.uuid }}" filesystem_path: "{{ btrfs_raid.path }}" - name: "/gitea/lfs" + name: "/forgejo/lfs" # Repositories and database are stored in NVME - filesystem_uuid: "{{ btrfs_nvme.uuid }}" filesystem_path: "{{ btrfs_nvme.path }}" - name: "/@rootfs/data/gitea/repositories" + name: "/@rootfs/data/forgejo/repositories" - filesystem_uuid: "{{ btrfs_nvme.uuid }}" filesystem_path: "{{ btrfs_nvme.path }}" - name: "/@rootfs/data/gitea/postgres" + name: "/@rootfs/data/forgejo/postgres" - - role: any.software.gitea + - role: any.software.forgejo-podman vars: - gitea_data_dir: "{{ btrfs_raid.path }}/gitea/data" - gitea_lfs_dir: "{{ btrfs_raid.path }}/gitea/lfs" - gitea_repositories_dir: "{{ btrfs_nvme.path }}/data/gitea/repositories" - postgres_data_dir: "{{ btrfs_nvme.path }}/data/gitea/postgres" + # General + forgejo_version: '11.0.11' + forgejo_postgres_version: '14.8' + + # Networking + forgejo_http_port: 8027 + forgejo_ssh_port: 8016 + forgejo_domain: 'git.rustybever.be' + forgejo_root_url: 'https://git.rustybever.be/' + + # Secrets + forgejo_lfs_jwt_secret: "{{ vault_gitea_lfs_jwt_secret }}" + forgejo_secret_key: "{{ vault_gitea_secret_key }}" + forgejo_internal_token: "{{ vault_gitea_internal_token }}" + forgejo_jwt_secret: "{{ vault_gitea_jwt_secret }}" + + # Data + forgejo_data_dir: "{{ btrfs_raid.path }}/forgejo/data" + forgejo_repositories_dir: "{{ btrfs_nvme.path }}/data/forgejo/repositories" + forgejo_lfs_dir: "{{ btrfs_raid.path }}/forgejo/lfs" + forgejo_postgres_dir: "{{ btrfs_nvme.path }}/data/forgejo/postgres" - role: any.tools.backup-scripts become: true vars: backups: - # TODO: gitea-data, gitea-lfs - - name: "gitea-postgres" + - name: "forgejo-postgres" type: "podman-postgres" user: "debian" - container: "systemd-gitea-postgres" - pg_user: "gitea" - database: "gitea" - - name: "gitea-repositories" + container: "systemd-forgejo-postgres" + pg_user: "forgejo" + database: "forgejo" + - name: "forgejo-repositories" type: "btrfs-subvolume" - path: "/data/gitea/repositories" + path: "/data/forgejo/repositories" + - name: "forgejo-data" + type: "btrfs-subvolume" + path: "{{ btrfs_raid.path }}/forgejo/data" + - name: "forgejo-lfs" + type: "btrfs-subvolume" + path: "{{ btrfs_raid.path }}/forgejo/lfs" - name: Set up Otter hosts: emma diff --git a/roles/any.software.forgejo-podman/README.md b/roles/any.software.forgejo-podman/README.md new file mode 100644 index 0000000..2ad827c --- /dev/null +++ b/roles/any.software.forgejo-podman/README.md @@ -0,0 +1,27 @@ +# `any.software.forgejo-podman` + +## Description + +Role that installs Forgejo along with a Postgresql database in Podman. + +## Configuration + +* General + * `forgejo_version`: version of Forgejo to install + * `forgejo_postgres_version`: version of PostgreSQL to install +* Networking + * `forgejo_ssh_port`: port to expose the SSH port to; will skip publishing port if omitted + * `forgejo_http_port`: port to expose the HTTP server to; will skip publishing port if omitted + * `forgejo_domain`: domain the server will be running on + * `forgejo_ssh_domain`: SSH domain setting, defaults to `forgejo_domain` + * `forgejo_root_url`: root URL setting +* Secrets + * `forgejo_lfs_jwt_secret`: the LFS JWT secret + * `forgejo_secret_key`: the `SECRET_KEY` variable + * `forgejo_internal_token`: the `INTERNAL_TOKEN` variable + * `forgejo_jwt_secret`: the JWT secret used for OAuth2 +* Data + * `forgejo_data_dir`: the directory regular data is stored in + * `forgejo_repositories_dir`: directory all repositories are stored in + * `forgejo_lfs_dir`: directory LFS objects are stored in + * `forgejo_postgres_dir`: data directory for the PostgreSQL database diff --git a/roles/any.software.forgejo-podman/handlers/main.yml b/roles/any.software.forgejo-podman/handlers/main.yml new file mode 100644 index 0000000..c8bf429 --- /dev/null +++ b/roles/any.software.forgejo-podman/handlers/main.yml @@ -0,0 +1,16 @@ +--- +- name: 'restart forgejo-app' + ansible.builtin.service: + name: 'forgejo-app' + state: 'restarted' + + scope: user + daemon_reload: true + +- name: 'restart forgejo-postgres' + ansible.builtin.service: + name: 'forgejo-postgres' + state: 'restarted' + + scope: user + daemon_reload: true diff --git a/roles/any.software.forgejo-podman/meta/main.yml b/roles/any.software.forgejo-podman/meta/main.yml new file mode 100644 index 0000000..32c83bc --- /dev/null +++ b/roles/any.software.forgejo-podman/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - role: any.tools.caddy + become: true diff --git a/roles/any.software.forgejo-podman/tasks/main.yml b/roles/any.software.forgejo-podman/tasks/main.yml new file mode 100644 index 0000000..d5ec9e7 --- /dev/null +++ b/roles/any.software.forgejo-podman/tasks/main.yml @@ -0,0 +1,55 @@ +--- +- name: Ensure configuration file is present + become: true + ansible.builtin.template: + src: "app.ini.j2" + dest: "{{ forgejo_data_dir }}/gitea/conf/app.ini" + mode: '0644' + owner: 'debian' + group: 'debian' + notify: 'restart forgejo-app' + +- name: Ensure forgejo.pod is present + ansible.builtin.template: + src: "forgejo.pod.j2" + dest: "/home/debian/.config/containers/systemd/forgejo.pod" + mode: '0755' + owner: 'debian' + group: 'debian' + notify: 'restart forgejo-app' + +- name: Ensure forgejo-app.container is present + ansible.builtin.template: + src: "forgejo-app.container.j2" + dest: "/home/debian/.config/containers/systemd/forgejo-app.container" + mode: '0755' + owner: 'debian' + group: 'debian' + notify: 'restart forgejo-app' + +- name: Ensure forgejo-postgres.container is present + ansible.builtin.template: + src: "forgejo-postgres.container.j2" + dest: "/home/debian/.config/containers/systemd/forgejo-postgres.container" + mode: '0755' + owner: 'debian' + group: 'debian' + notify: 'restart forgejo-postgres' + +- name: Ensure Caddyfile is present + become: true + ansible.builtin.template: + src: 'forgejo.Caddyfile.j2' + dest: '/etc/caddy/forgejo.Caddyfile' + owner: root + group: root + mode: '0644' + notify: reload caddy + when: 'forgejo_domain is defined' + +- name: Allow Forgejo SSH connections + become: true + community.general.ufw: + port: "{{ forgejo_ssh_port }}" + rule: 'allow' + when: 'forgejo_ssh_port is defined' diff --git a/roles/any.software.forgejo-podman/templates/app.ini.j2 b/roles/any.software.forgejo-podman/templates/app.ini.j2 new file mode 100644 index 0000000..3643eb0 --- /dev/null +++ b/roles/any.software.forgejo-podman/templates/app.ini.j2 @@ -0,0 +1,126 @@ +APP_NAME = The Rusty Bever +RUN_MODE = prod +RUN_USER = git +WORK_PATH = /data/gitea + +[repository] +ROOT = /data/git/repositories +; Makes public the default option when creating a repo +DEFAULT_PRIVATE = public +; Disables releases, projects & wiki by default for new repos (but can be enabled when needed) +DEFAULT_REPO_UNITS = repo.code,repo.issues,repo.pulls +; Might as well be compatible with +DEFAULT_BRANCH = main + +[repository.pull-request] +WORK_IN_PROGRESS_PREFIXES = WIP:,[WIP]:,Draft:,[Draft]: + +[repository.local] +LOCAL_COPY_PATH = /data/gitea/tmp/local-repo + +[repository.upload] +TEMP_PATH = /data/gitea/uploads + +[ui] +; Always show the full name of a user when possible +DEFAULT_SHOW_FULL_NAME = true +THEMES = auto,gitea,arc-green,gitea-modern + +[server] +APP_DATA_PATH = /data/gitea +DOMAIN = {{ forgejo_domain }} +SSH_DOMAIN = {{ forgejo_ssh_domain | default(forgejo_domain) }} +HTTP_PORT = 3000 +ROOT_URL = {{ forgejo_root_url }} +DISABLE_SSH = false +SSH_PORT = 22 +SSH_LISTEN_PORT = 22 +LFS_START_SERVER = true +OFFLINE_MODE = false +LFS_JWT_SECRET = {{ forgejo_lfs_jwt_secret }} + +[lfs] +PATH = /data/git/lfs + +[database] +PATH = /data/gitea/gitea.db +DB_TYPE = postgres +HOST = localhost:5432 +NAME = gitea +USER = gitea +PASSWD = gitea +LOG_SQL = false +SCHEMA = +SSL_MODE = disable +CHARSET = utf8 + +[indexer] +ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve + +[session] +PROVIDER_CONFIG = /data/gitea/sessions +PROVIDER = file + +[picture] +AVATAR_UPLOAD_PATH = /data/gitea/avatars +REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars +DISABLE_GRAVATAR = false +ENABLE_FEDERATED_AVATAR = true + +[attachment] +PATH = /data/gitea/attachments + +[log] +MODE = console +LEVEL = info +REDIRECT_MACARON_LOG = true +MACARON = console +ROOT_PATH = /data/gitea/log + +; disable router logs +logger.router.MODE = + +[log.console] +MODE = console +FLAGS = journaldflags +COLORIZE = false + +[security] +INSTALL_LOCK = true +MIN_PASSWORD_LENGTH = 12 +PASSWORD_COMPLEXITY = lower,upper,digit +SECRET_KEY = {{ forgejo_secret_key }} +INTERNAL_TOKEN = {{ forgejo_internal_token }} + +[service] +DISABLE_REGISTRATION = true +REQUIRE_SIGNIN_VIEW = false +REGISTER_EMAIL_CONFIRM = false +ENABLE_NOTIFY_MAIL = false +ALLOW_ONLY_EXTERNAL_REGISTRATION = false +ENABLE_CAPTCHA = false +DEFAULT_KEEP_EMAIL_PRIVATE = false +DEFAULT_ALLOW_CREATE_ORGANIZATION = true +DEFAULT_ENABLE_TIMETRACKING = true +NO_REPLY_ADDRESS = noreply.localhost + +[mailer] +ENABLED = false + +[openid] +ENABLE_OPENID_SIGNIN = true +ENABLE_OPENID_SIGNUP = false + +[oauth2] +JWT_SECRET = {{ forgejo_jwt_secret }} + +[other] +SHOW_FOOTER_VERSION = false +SHOW_FOOTER_TEMPLATE_LOAD_TIME = false + +[cron.delete_repo_archives] +ENABLED = true +SCHEDULE = @weekly + +[metrics] +enabled = true diff --git a/roles/any.software.forgejo-podman/templates/forgejo-app.container.j2 b/roles/any.software.forgejo-podman/templates/forgejo-app.container.j2 new file mode 100644 index 0000000..e71bd71 --- /dev/null +++ b/roles/any.software.forgejo-podman/templates/forgejo-app.container.j2 @@ -0,0 +1,19 @@ +# vim: ft=systemd +[Unit] +Requires=forgejo-postgres.service +After=forgejo-postgres.service + +[Container] +Image=codeberg.org/forgejo/forgejo:{{ forgejo_version }} +Pod=forgejo.pod + +Volume={{ forgejo_data_dir }}:/data +Volume={{ forgejo_repositories_dir }}:/data/git/repositories +Volume={{ forgejo_lfs_dir }}:/data/git/lfs +Volume=/etc/localtime:/etc/localtime:ro + +[Service] +Restart=always + +[Install] +WantedBy=default.target diff --git a/roles/any.software.forgejo-podman/templates/forgejo-postgres.container.j2 b/roles/any.software.forgejo-podman/templates/forgejo-postgres.container.j2 new file mode 100644 index 0000000..a3da40b --- /dev/null +++ b/roles/any.software.forgejo-podman/templates/forgejo-postgres.container.j2 @@ -0,0 +1,18 @@ +# vim: ft=systemd +[Container] +Image=docker.io/postgres:{{ forgejo_postgres_version }}-alpine +Pod=forgejo.pod + +Environment=POSTGRES_USER=gitea POSTGRES_PASSWORD=gitea POSTGRES_DB=gitea + +HealthCmd=["pg_isready","-U","gitea"] +HealthInterval=30s +HealthRetries=3 +HealthStartPeriod=30s +HealthTimeout=5s +Notify=Healthy + +Volume={{ forgejo_postgres_dir }}:/var/lib/postgresql/data + +[Service] +Restart=always diff --git a/roles/any.software.forgejo-podman/templates/forgejo.Caddyfile.j2 b/roles/any.software.forgejo-podman/templates/forgejo.Caddyfile.j2 new file mode 100644 index 0000000..39a4f48 --- /dev/null +++ b/roles/any.software.forgejo-podman/templates/forgejo.Caddyfile.j2 @@ -0,0 +1,5 @@ +{{ forgejo_domain }} { + reverse_proxy localhost:{{ forgejo_http_port }} { + header_down +X-Robots-Tag "none" + } +} diff --git a/roles/any.software.forgejo-podman/templates/forgejo.pod.j2 b/roles/any.software.forgejo-podman/templates/forgejo.pod.j2 new file mode 100644 index 0000000..eda2099 --- /dev/null +++ b/roles/any.software.forgejo-podman/templates/forgejo.pod.j2 @@ -0,0 +1,8 @@ +# vim: ft=systemd +[Pod] +{% if forgejo_ssh_port is defined %} +PublishPort={{ forgejo_ssh_port }}:22 +{% endif %} +{% if forgejo_http_port is defined %} +PublishPort={{ forgejo_http_port }}:3000 +{% endif %}