Files
spacestation/capytal/forge.nix
Gustavo "Guz" L de Mello 470d719f80 feat(capytal,gitea)!: migrate from https://forge.capytal.company to https://code.capytal.cc
A new forge is now used, it is pretty much equal to before, but now we
are using (a fork of) Gitea instead of Forgejo. Gitea was choosen
because provides more features that we need compared to Forgejo and it
has a more modern codebase to fork and customize. The fork can be found
at https://code.capytal.cc/loreddev/gitea, it mostly provides a new
default theme and custom UI changes.
2025-10-11 09:21:21 -03:00

351 lines
10 KiB
Nix

{
config,
inputs,
lib,
self,
pkgs,
...
}: let
cfg = config.services.forgejo;
gitea = config.services.gitea;
in {
imports = [
self.nixosModules.gitea
];
services.gitea = {
enable = true;
package = inputs.loreddev-gitea.packages.${pkgs.system}.default;
lfs.enable = true;
settings = with lib; let
initList = l: (concatStringsSep "," l);
in rec {
DEFAULT = {
APP_NAME = "Capytal Code";
};
repository = {
DEFAULT_REPO_UNITS = initList [
"repo.code"
"repo.issues"
"repo.pulls"
];
DEFAULT_TEMPLATE_REPO_UNITS = repository.DEFAULT_REPO_UNITS;
};
"repository.pull-request" = {
CLOSE_KEYWORDS = initList [
# en-US
"close"
"closes"
"closed"
"fix"
"fixes"
"fixed"
"resolve"
"resolves"
"resolved"
# pt-BR
"corrige"
"completa"
"fecha"
"implementa"
"resolve"
"termina"
];
};
"repository.signing" = {
DEFAULT_TRUST_MODEL = "committer";
};
"ui.meta" = {
AUTHOR = "Capytal";
DESCRIPTION = replaceString "\n" " " ''
Software forge dedicated for hosting official projects from Capytal and it's members.
Explore and discover the source-code of our commercial user-facing products, internal
developer-focused libraries, and infraestructure setups.
'';
KEYWORDS = initList [
"capytal"
"capytal code"
"capytal-code"
"git"
"gitea"
"projects"
"development"
"open source"
"open-source"
];
};
server = {
DOMAIN = "code.capytal.cc";
ROOT_URL = "https://${server.DOMAIN}";
PUBLIC_URL_DETECTION = "auto";
HTTP_PORT = 9964;
};
database = {
DB_TYPE = "sqlite3";
NAME = "gitea";
USER = "gitea";
SQLITE_JOURNAL_MODE = "WAL";
};
security = {
INSTALL_LOCK = true;
COOKIE_REMEMBER_NAME = "__Host-capytal_code_forge_incredible";
PASSWORD_COMPLEXITY = initList ["lower" "upper" "digit" "spec"];
PASSWORD_CHECK_PWN = true;
};
service = {
REGISTER_MANUAL_CONFIRM = true;
REVERSE_PROXY_TRUSTED_PROXIES = "127.0.0.0/8,::1/128";
DISABLE_REGISTRATION = true;
DEFAULT_KEEP_EMAIL_PRIVATE = true;
DEFAULT_ALLOW_CREATE_ORGANIZATION = false;
DEFAULT_USER_IS_RESTRICTED = true;
SHOW_REGISTRATION_BUTTON = false;
ALLOW_ONLY_INTERNAL_REGISTRATION = true;
VALID_SITE_URL_SCHEMES = initList ["https"];
};
qos = {
# For endpoints not protected by Anubis and protect from overload in general.
ENABLED = true;
};
cache = {
ADAPTER = "twoqueue";
HOST = builtins.toJSON {
size = 1000;
recent_ratio = 0.25;
ghost_ratio = 0.5;
};
};
session = {
COOKIE_SECURE = true;
COOKIE_NAME = "__Host-i_like_capytal_code_forge";
SAME_SITE = "strict";
};
picture = {
DISABLE_GRAVATAR = true; # Deprecated
ENABLE_FEDERATED_AVATAR = false; # Deprecated
};
"cron.delete_repo_archives" = {
ENABLED = true;
};
"cron.git_gc_repos" = {
ENABLED = true;
};
oauth2 = {
ENABLED = true;
};
federation = {
ENABLED = true;
};
lfs = {};
storage = {
STORAGE_TYPE = "minio";
MINIO_USE_SSL = false;
MINIO_ENDPOINT = "localhost:3461";
MINIO_BUCKET = "gitea";
MINIO_LOCATION = config.services.garage.settings.s3_api.s3_region;
};
"storage.repo-archive" = {};
"repo-archive" = {};
actions = {
ENABLE = false; # Temporarily
DEFAULT_ACTIONS_URL = "self";
};
};
secrets = {
server = {
LFS_JWT_SECRET = config.sops.secrets."gitea/server/lfs_jwt_secret".path;
};
security = {
SECRET_KEY = config.sops.secrets."gitea/security/secret_key".path;
INTERNAL_TOKEN = config.sops.secrets."gitea/security/internal_token".path;
};
oauth2 = {
JWT_SECRET = config.sops.secrets."gitea/oauth2/jwt_secret".path;
};
storage = {
MINIO_ACCESS_KEY_ID = config.sops.secrets."gitea/storage/access_key_id".path;
MINIO_SECRET_ACCESS_KEY = config.sops.secrets."gitea/storage/secret_access_key".path;
};
};
};
services.gitea-actions-runner = {
instances = {
"gitea-runner-1" = {
enable = true;
name = "Gitea Runner (${config.networking.hostName}) 1";
url = gitea.settings.server.ROOT_URL;
tokenFile = config.sops.secrets."gitea/actions/token".path;
labels = [
"alpine-3.22:docker://data.forgejo.org/oci/alpine:3.22"
"golang-1.24:docker://data.forgejo.org/oci/golang:1.24-alpine3.22"
"ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
];
};
};
};
# systemd.services.gitea-custom = let
# gitea = config.services.gitea;
# rsync = lib.getExe pkgs.rsync;
# in {
# before = [
# "gitea-secrets.service"
# "gitea.service"
# ];
# script = ''
# ${rsync} -av "${./assets}" "${gitea.customDir}/public/assets"
# '';
# serviceConfig = {
# Type = "oneshot";
# RemainAfterExit = true;
# User = gitea.user;
# Group = gitea.group;
# ReadWritePaths = [gitea.customDir];
# UMask = "0077";
# };
# };
services.anubis.instances."gitea" = {
settings = {
BIND = ":${toString (gitea.settings.server.HTTP_PORT + 2)}";
BIND_NETWORK = "tcp";
METRICS_BIND = ":${toString (gitea.settings.server.HTTP_PORT + 3)}";
METRICS_BIND_NETWORK = "tcp";
SERVE_ROBOTS_TXT = true;
TARGET = "http://localhost:${toString gitea.settings.server.HTTP_PORT}";
ED25519_PRIVATE_KEY_HEX_FILE = config.sops.secrets."anubis/gitea/hex_file".path;
};
};
services.caddy.virtualHosts = let
redir = {
extraConfig = ''
redir https://code.capytal.cc{uri} permanent
'';
};
in {
":${toString (gitea.settings.server.HTTP_PORT + 1)}" = {
extraConfig = ''
reverse_proxy http://localhost${config.services.anubis.instances."gitea".settings.BIND} {
header_up X-Http-Version {http.request.proto}
header_up X-Real-Ip {remote_host}
}
'';
};
# Old ports used by legacy https://forge.capytal.company
":9961" = redir;
":9962" = redir;
};
# services.forgejo = {
# enable = true;
# package = pkgs.forgejo;
# settings = let
# initList = l: (lib.strings.concatStringsSep "," l);
# in {
# DEFAULT = {
# APP_NAME = "Capytal Code";
# };
# actions = {
# ENABLED = true;
# DEFAULT_ACTIONS_URL = "https://data.forgejo.org";
# };
# admin = {
# DISABLE_REGULAR_ORG_CREATION = true;
# USER_DISABLED_FEATURES = "deletion manage_ssh_keys manage_gpg_keys";
# EXTERNAL_USER_DISABLED_FEATURES = "deletion manage_ssh_keys manage_gpg_keys";
# };
# database = {
# HOST = "127.0.0.1:${toString config.services.postgresql.settings.port}";
# NAME = "forgejo";
# USER = "forgejo";
# SSL_MODE = "disable";
# };
# repository = {
# DEFAULT_REPO_UNITS = initList [
# "repo.code"
# "repo.issues"
# "repo.pulls"
# ];
# };
# security = {
# REVERSE_PROXY_TRUSTED_PROXIES = "127.0.0.0/8,::1/128";
# };
# server = rec {
# HTTP_PORT = 9960;
# DOMAIN = "forge.capytal.company";
# ROOT_URL = "https://${DOMAIN}";
# };
# service = {
# DISABLE_REGISTRATION = true;
# };
# storage = {
# STORAGE_TYPE = "minio";
# MINIO_USE_SSL = false;
# MINIO_ENDPOINT = "127.0.0.1:3461";
# MINIO_BUCKET = "forgejo";
# MINIO_LOCATION = config.services.garage.settings.s3_api.s3_region;
# };
# ui = {
# # DEFAULT_THEME = "capytal-dark";
# };
# };
# secrets = {
# storage = {
# MINIO_ACCESS_KEY_ID = "${config.sops.secrets."forgejo/s3/key".path}";
# MINIO_SECRET_ACCESS_KEY = "${config.sops.secrets."forgejo/s3/secret".path}";
# };
# };
# };
# services.gitea-actions-runner = {
# package = pkgs.forgejo-actions-runner;
# instances = {
# "forgejo-runner-1" = {
# enable = true;
# name = "Forgejo Runner (${config.networking.hostName}) 1";
# url = config.services.forgejo.settings.server.ROOT_URL;
# tokenFile = config.sops.secrets."forgejo/actions/token".path;
# labels = [
# "alpine-3.22:docker://data.forgejo.org/oci/alpine:3.22"
# "golang-1.24:docker://data.forgejo.org/oci/golang:1.24-alpine3.22"
# "node-24:docker://node:24-bullseye"
# ];
# };
# };
# };
#
# users.users."${cfg.user}".packages = [
# (pkgs.symlinkJoin {
# paths = [pkgs.forgejo];
# buildInputs = [pkgs.makeWrapper];
# postFixup = ''
# wrapProgram $out/bin/gitea \
# --add-flags --config '${cfg.customDir}/conf/app.ini'
# '';
# inherit (pkgs.forgejo) name pname meta;
# })
# ];
#
# services.anubis.instances."forgejo" = {
# settings = {
# BIND = ":${toString (cfg.settings.server.HTTP_PORT + 2)}";
# BIND_NETWORK = "tcp";
# METRICS_BIND = ":${toString (cfg.settings.server.HTTP_PORT + 3)}";
# METRICS_BIND_NETWORK = "tcp";
# SERVE_ROBOTS_TXT = true;
# TARGET = "http://localhost:${toString cfg.settings.server.HTTP_PORT}";
# ED25519_PRIVATE_KEY_HEX_FILE = config.sops.secrets."anubis/forgejo/hex_file".path;
# };
# };
# services.caddy.virtualHosts.":${toString (cfg.settings.server.HTTP_PORT + 1)}" = {
# extraConfig = ''
# reverse_proxy http://localhost${config.services.anubis.instances."forgejo".settings.BIND} {
# header_up X-Real-Ip {remote_host}
# }
# '';
# };
}