Gustavo "Guz" L. de Mello
2024-04-12 22:59:19 -03:00
parent 99350338f2
commit e1901c2954
6 changed files with 139 additions and 258 deletions

View File

@@ -22,7 +22,7 @@ in {
default = lesser-secrets;
};
};
config = {
config = with lib; {
environment.systemPackages = with pkgs; [
sops
];
@@ -34,16 +34,16 @@ in {
owner = config.users.users."guz".name;
};
sops.secrets."forgejo/user1/name" = {
sops.secrets."forgejo/user1/name" = mkIf config.services.forgejo.enable {
owner = config.services.forgejo.user;
};
sops.secrets."forgejo/user1/password" = {
sops.secrets."forgejo/user1/password" = mkIf config.services.forgejo.enable {
owner = config.services.forgejo.user;
};
sops.secrets."forgejo/user1/email" = {
sops.secrets."forgejo/user1/email" = mkIf config.services.forgejo.enable {
owner = config.services.forgejo.user;
};
sops.secrets."forgejo/git-password" = {
sops.secrets."forgejo/git-password" = mkIf config.services.forgejo.enable {
owner = config.services.forgejo.user;
};

View File

@@ -63,39 +63,22 @@ in {
secrets.services;
networking.firewall.allowedTCPPorts = [80 433];
services.openssh.enable = true;
services.forgejo = {
enable = true;
actions = {
enable = true;
token = secrets.services.forgejo.actions-token;
url = "http://${config.services.tailscale.deviceUrl}:${toString secrets.services.forgejo.port}";
};
users = {
user1 = {
name = /. + config.sops.secrets."forgejo/user1/name".path;
password = /. + config.sops.secrets."forgejo/user1/password".path;
email = /. + config.sops.secrets."forgejo/user1/email".path;
admin = true;
};
};
settings = {
server = {
ROOT_URL = "https://${secrets.services.forgejo.domain}";
DOMAIN = "${secrets.services.forgejo.domain}";
HTTP_PORT = secrets.services.forgejo.port;
DOMAIN = secrets.services.forgejo.domain;
ROOT_URL = "https://${secrets.services.forgejo.domain}";
};
};
};
home-manager-helper.users."${config.services.forgejo.user}" = {
name = "${config.services.forgejo.user}";
hashedPasswordFile = builtins.toString config.sops.secrets."forgejo/git-password".path;
isSystemUser = true;
homeDirectory = "/var/lib/forgejo";
extraGroups = ["wheel" "networkmanager"];
useDefaultShell = true;
};
services.openssh.enable = true;
services.tailscale = {
enable = true;

View File

@@ -1,12 +1,12 @@
{
config,
lib,
pkgs,
utils,
...
}: let
{ config
, lib
, pkgs
, utils
, ...
}:
let
cfg = config.services.forgejo;
yamlFormat = pkgs.formats.yaml {};
yamlFormat = pkgs.formats.yaml { };
users = builtins.attrValues (builtins.mapAttrs
(username: info: {
name =
@@ -19,150 +19,136 @@
})
cfg.users);
initList = l: lib.strings.concatStringsSep "," l;
in {
imports = [];
in
{
imports = [ ];
options.services.forgejo = with lib;
with lib.types; {
handleUndeclaredUsers = mkOption {
type = bool;
default = false;
};
users = mkOption {
type = attrsOf (submodule ({
config,
lib,
...
}:
with lib;
with lib.types; {
options = {
name = mkOption {
type = nullOr (either str path);
default = null;
with lib.types; {
handleUndeclaredUsers = mkOption {
type = bool;
default = false;
};
users = mkOption {
type = attrsOf (submodule ({ config
, lib
, ...
}:
with lib;
with lib.types; {
options = {
name = mkOption {
type = nullOr (either str path);
default = null;
};
password = mkOption {
type = either str path;
};
email = mkOption {
type = either str path;
};
admin = mkOption {
type = bool;
default = false;
};
};
password = mkOption {
type = either str path;
};
email = mkOption {
type = either str path;
};
admin = mkOption {
type = bool;
default = false;
};
};
}));
default = {};
};
actions = {
enable = mkEnableOption "";
hostPackages = mkOption {
type = listOf package;
default = with pkgs; [
bash
coreutils
curl
gawk
gitMinimal
gnused
nodejs
wget
];
}));
default = { };
};
labels = mkOption {
type = listOf str;
default = [
"host:host"
"shell:host://-self-hosted"
"debian-latest:docker://node:18-bullseye"
"ubuntu-latest:docker://node:18-bullseye"
"debian-slim:docker://node:18-bullseye-slim"
"ubuntu-slim:docker://node:18-bullseye-slim"
"alpine-latest:docker://alpine:latest"
];
};
name = mkOption {
type = str;
default = "Forgejo ${toString cfg.settings.server.HTTP_PORT} - Actions Runner";
};
package = mkOption {
type = package;
default = pkgs.forgejo-actions-runner;
};
settings = mkOption {
type = yamlFormat.type;
default = {};
};
token = mkOption {
type = nullOr str;
default = null;
};
tokenFile = mkOption {
type = nullOr (either path str);
default = null;
};
url = mkOption {
type = str;
default = cfg.settings.server.ROOT_URL;
actions = {
enable = mkOption {
type = bool;
default = cfg.enable;
};
token = mkOption {
type = str;
};
url = mkOption {
type = str;
default = "http://localhost:${toString cfg.settings.server.HTTP_PORT}";
};
};
};
};
config = with lib;
mkIf cfg.enable {
# this opens the port for the internal actions be able to clone and interact with the instance
networking.firewall.allowedTCPPorts =
mkIf cfg.actions.enable [cfg.settings.server.HTTP_PORT];
networking.firewall.allowedTCPPorts = mkIf cfg.settings.actions.ENABLED [
cfg.settings.server.HTTP_PORT
];
networking.firewall.allowedUDPPorts = mkIf cfg.settings.actions.ENABLED [
cfg.settings.server.HTTP_PORT
];
services.forgejo.settings = {
actions = {
ENABLED = mkDefault cfg.actions.enable;
DEFAULT_ACTIONS_URL = mkDefault cfg.settings.server.ROOT_URL;
};
repository = {
DEFAULT_REPO_UNITS = mkDefault (initList [
"repo.code"
"repo.issues"
"repo.pulls"
]);
DISABLED_REPO_UNITS = mkIf (!cfg.actions.enable) (mkDefault "repo.actions");
};
security = {
ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET = mkDefault true;
};
server = {
HTTP_PORT = mkDefault 3617;
DOMAIN =
mkIf config.services.tailscale.enable
(mkDefault "${config.services.tailscale.deviceUrl}");
};
service = {
DISABLE_REGISTRATION = mkDefault true;
users.users."${cfg.user}" = {
home = cfg.stateDir;
useDefaultShell = true;
group = cfg.group;
isSystemUser = true;
extraGroups = [ "wheel" "networkmanager" ];
};
users.groups."${cfg.group}" = { };
services.forgejo = {
user = mkDefault "git";
group = mkDefault cfg.user;
settings = {
DEFAULT = {
APP_NAME = mkDefault "Forgejo: Beyond coding. We forge.";
};
actions = {
ENABLED = mkDefault cfg.actions.enable;
DEFAULT_ACTIONS_URL = mkDefault "http://localhost:${toString cfg.settings.server.HTTP_PORT}";
};
repository = {
DEFAULT_REPO_UNITS = mkDefault (initList [
"repo.code"
]);
DISABLED_REPO_UNITS = mkIf (!cfg.actions.enable) (mkDefault (initList [
"repo.actions"
]));
};
service = {
# DISABLE_REGISTRARION = mkDefault true;
};
};
};
virtualisation.docker.enable = mkIf cfg.settings.actions.ENABLED (mkDefault true);
services.gitea-actions-runner.instances."generatedForgejo${toString cfg.settings.server.HTTP_PORT}" = mkIf cfg.actions.enable {
enable = mkDefault true;
hostPackages = mkDefault cfg.actions.hostPackages;
labels = mkDefault cfg.actions.labels;
name = mkDefault cfg.actions.name;
settings = mkDefault cfg.actions.settings;
url = mkDefault cfg.actions.url;
token = cfg.actions.token;
};
systemd.services = {
"${utils.escapeSystemdPath "generatedForgejo${toString cfg.settings.server.HTTP_PORT}"}" = {
serviceConfig.User = mkIf cfg.actions.enable (mkDefault cfg.user);
virtualisation.docker.enable = mkIf cfg.actions.enable (mkDefault true);
services.gitea-actions-runner = mkIf cfg.actions.enable {
package =
if config.services.gitea.enable
then pkgs.gitea-actions-runner
else pkgs.forgejo-actions-runner;
instances."forgejo${toString cfg.settings.server.HTTP_PORT}" = {
enable = mkDefault true;
token = mkDefault cfg.actions.token;
name = mkDefault "${cfg.settings.DEFAULT.APP_NAME} - Actions";
url = cfg.actions.url;
labels = mkDefault [
/*
Remember to install git on these images so actions/checkout can work,
without it, the actions tries to use the /api/v3/repos/{user}/{repo}/tarball/{ref}
api endpoint, which Gitea/Forgejo doesn't has.
*/
"ubuntu-latest:docker://gitea/runner-images:ubuntu-latest-slim"
"ubuntu-latest-full:docker://gitea/runner-images:ubuntu-latest"
];
settings = {
runner = {
insecure = true;
};
};
};
};
/*
systemd.services."forgejo-users-setup" = with builtins; {
script = ''
function gum() { ${pkgs.gum}/bin/gum "$@"; }
function forgejo() {
local config_file="${toString cfg.stateDir}/custom/conf/app.ini";
touch $config_file
${cfg.package}/bin/gitea --config $config_file "$@"
# local config_file="${toString cfg.stateDir}/custom/conf/app.ini";
# touch $config_file
${cfg.package}/bin/gitea \
--work-path ${cfg.stateDir} \
"$@"
}
function fjuser() { forgejo admin user "$@"; }
function awk() { ${pkgs.gawk}/bin/awk "$@"; }
@@ -204,96 +190,6 @@ in {
'')
users)}
'';
wantedBy = ["multi-user.target"];
after = ["forgejo.service"];
serviceConfig = {
Type = "oneshot";
User = cfg.user;
Group = cfg.group;
};
};
/*
systemd.services."homelab-forgejo-setup" = with builtins; {
script = ''
configFile="${toString cfg.stateDir}/custom/conf/app.ini";
touch $configFile
gum="${pkgs.gum}/bin/gum"
forgejo="${cfg.package}/bin/gitea --config $configFile"
user="$forgejo admin user"
awk="${pkgs.gawk}/bin/awk"
declaredUsers=(${toString (map (user: "${
if isPath user.name
then "$(cat ${toString user.name})"
else user.name
}")
users)});
$gum log --structured --time timeonly --level info "HANDLING UNDECLARED USERS"
$user list | $awk '{print $2}' | tail -n +2 | while read username; do
if printf '%s\0' "''${declaredUsers[@]}" | grep -Fxqz -- "$username"; then
$gum log --structured --time timeonly --level warn "Declared user already exists, ignoring" username $username;
else
if [[ "$($user list | tail -n +2 | $awk '{print $2 " " $5}' | grep "$username " | $awk '{print $2}')" == "true" ]]; then
$gum log --structured --time timeonly --level warn "Undeclared user is a ADMIN, ignoring" username $username;
else
${
if cfg.handleUndeclaredUsers
then ''
$gum log --structured --time timeonly --level warn "DELETING undeclared user" username $username;
$user delete -u "$username";
''
else ''
$gum log --structured --time timeonly --level warn "UNDECLARED user, please declare it in the config so it's reproducible" username "$username";
''
}
fi
fi
done
${toString (map (user: ''
username="${
if isPath user.name
then "\"$(cat ${toString user.name})\""
else user.name
}";
email="${
if isPath user.email
then "\"$(cat ${toString user.email})\""
else user.email
}";
password="${
if isPath user.password
then "\"$(cat ${toString user.password})\""
else user.password
}";
if [[ "$($user list | grep "$username" | $awk '{print $2}')" ]]; then
$gum log --structured --time timeonly --level warn "User with username already exists" username $username;
elif [[ "$($user list | grep "$email" | $awk '{print $3}')" ]]; then
$gum log --structured --time timeonly --level warn "User with email already exists" email $email;
else
$gum log --structured --time timeonly --level info ${
if user.admin
then "Creating ADMIN user"
else "Creating user"
} username $username email $email password $password;
$user create --username $username --email $email --password $password ${
if user.admin
then "--admin"
else ""
};
fi
'')
users)}
'';
wantedBy = [ "multi-user.target" ];
after = [ "forgejo.service" ];
serviceConfig = {

View File

@@ -72,7 +72,7 @@ function set-user() {
fjuser create --username "$username" \
--email "$email" \
--passowrd "$password" \
--password "$password" \
--admin
else
gum log --structured \
@@ -84,8 +84,7 @@ function set-user() {
fjuser create --username "$username" \
--email "$email" \
--passowrd "$password"
--password "$password"
fi
fi
}

View File

@@ -6,7 +6,7 @@
"forgejo": {
"domain": "ENC[AES256_GCM,data:DJDExE7VVmAk4ZLhOkTfD2wBY5i1,iv:tnOgrKCpglvDyk75mnmeoiz2trmD3r3wCL2etHmALC4=,tag:rAiEK9U48cR1q+W7Zbkhvg==,type:str]",
"port": "ENC[AES256_GCM,data:ydSACw==,iv:0RWRLLCU8YyYmOmTawns2Iy+ABiBFbBqgQ10+buZNt0=,tag:3QW0NzbKeUkcfYh/5my3fA==,type:float]",
"actions-token": "ENC[AES256_GCM,data:j9hpNPmbWC2z862ca8RtmB1A62P3F3L6hS1WdpCXiCEunDvHOo9qcg==,iv:DSWebuZqdwx8R9MaJgSvIVRfUOJO7OpR3ORjgp6amzw=,tag:/bPMMWsfeoKbY47JQgC38Q==,type:str]"
"actions-token": "ENC[AES256_GCM,data:eNZtfpBt0ZjgLrykGKGEL3gtKCHHE+UWaDATgi0QHBGj7ZZX7ROuKQ==,iv:J8wmqFVmi8sarGupw/F4PP20HdaGTrxC4pF8GERwZxs=,tag:wZve5TI4/NpacMpHtpBnoA==,type:str]"
},
"adguard": {
"domain": "ENC[AES256_GCM,data:QquWEbgpXY13UMV9BTXplQ5LhSgv,iv:0AstA5oaS8714QME3QK0/aiv9Khqk1bLCcFdCEPn+IA=,tag:XXIWjIjHQ0gZFSFBHU49Ag==,type:str]",
@@ -24,8 +24,8 @@
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnL3dCY1VLMmoxRFRmS0Ir\nV0ppTnI0RE5ZMjcvRGNPWkNxWFdJYTBDTG00ClRGQkh1UStGTmc0RE5aNy9nL3FI\nbHJIa3hLR0ZkTjd6WkFzOFkzeFdMNUEKLS0tIDBidk93Qy9LenFlSGZ2aEpuTUFt\nWVM2eS9UdXAvbzE4eEdKMjVEM3RLdm8KKeIhk+YOKVL9Y19lLyb6/Pxv8rbewK2e\nLm96jx+LOMOCFcQGxuFKWqQbTB4br/cPvRKSY5jFmFWqVg7pCPTAzQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2024-04-07T21:39:36Z",
"mac": "ENC[AES256_GCM,data:29gkzrSMR1O6PRVMyBuNxRwvpAHwvY+VZxzfkzukxRdlQ8GKaskVf/xjIzTlojsRZDLRBIP7ZGfCRsmYskwfkoqEZRfQ+/LwEXdol/Lhyd+OM9aP7h+GP9+qjf4KN7JvJSzj3HNdUVJNULDmAFdRaKAkIkRl5lCrVUGZJTgfj3s=,iv:GVGchkF1YllSUePk+cIz2op50OLaeuTpizbuOOF7x0E=,tag:/ZoZllvCtKdaikA5TzsdGA==,type:str]",
"lastmodified": "2024-04-11T18:25:11Z",
"mac": "ENC[AES256_GCM,data:68Knkm4T7GteUXCN6TZy+E5LDIgNnRuNlu/2iBbGeJBAovKFiOdP0vUkvqBQL8zkTJk4y5QQKAtu8w9V0MtL9dp61z9nhRbiCbGNkjGoFLfsedTGvifR0HfHy1r4tZKc7A10gn8706q72BEJ+2x3m+6mb2Xh95erXEPl/nyKJZ0=,iv:E96M8LjI2UHced4iNEVkRo2uZWDQR5QudFqyj0JEenw=,tag:MIrn+aJljyFqWbX8R/nckw==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.8.1"

View File

@@ -1,7 +1,10 @@
guz:
password: ENC[AES256_GCM,data:zlO5xSFho7TXjFv62lgFir9SAgn+UE6XjdNEvIAgmQG9oDkthfgxO84wYdI0mQDwRIIs2PmSdBRfo0DPc3hji+ySCrItolPL8g==,iv:MZfhTxwfcbmXh5C6DkQhnY9NQGdE8zEwwvFOHQiUgKY=,tag:JjJN2bYcSXNN3ueGj5RNLg==,type:str]
network:
ip: ENC[AES256_GCM,data:AkbNOQLXRKLYjU2ywg==,iv:xqdTPCUYiT/cPe2zAbBJ7fUiEMViW9LZND4j0DdydLY=,tag:tq6nA5fGH4/mAvF6InUFgQ==,type:str]
localIp: ENC[AES256_GCM,data:PK8THL9NW//2sal1,iv:9h3f255rIgedYToVaUGuQ9RzD33V8sczRWsZe+rTyC0=,tag:OoJbes6k0FqxXzGQ8ZG0aA==,type:str]
forgejo:
git-password: ENC[AES256_GCM,data:SDyFBCwTxnZ1E6R/8HZCBIBj4AREYfqWrgzSEQ6SA3BDGPFsHghiVmF+Jt4omdzUQSoCCblMBsAx0NQBbBJrCbEoBWtybRM7Cg==,iv:KbtjXW1F8YJeapVpEkf8AdXhojmhOQKxG8nCZv7vW4k=,tag:odrL53KeKLVD5AoQB14veA==,type:str]
user1:
name: ENC[AES256_GCM,data:UL3g,iv:+ftGx57fhzN06DuLItxZTc7lXX2g4MhqrEqnDjk4Aug=,tag:ZNpwWuPYhBzDjRQBKikCDA==,type:str]
password: ENC[AES256_GCM,data:KXx9Kv9f9UP3sAU=,iv:bCBv+IEieR+RGjgjXLKMLlsqoBOLLYjvT167QIxxFmA=,tag:dPNUcrBrE66xDlFJltmIKg==,type:str]
@@ -26,8 +29,8 @@ sops:
amRmVkVoS2RqeEs3OXZVeTlsZUVEV28K1WcbGJHT8LMah5b7NN1psiucTl1OfZYO
4T3RDSQMB3qj1TGQSdixjwRRKbMGtL3LXnvkNd+caVi5Z9OkF1O9Yg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-02-11T21:34:36Z"
mac: ENC[AES256_GCM,data:wJvE4drJ+DTe6lpOj+bVryf6bPrLFwvIHtj0ugpf+rABEfCBC7qvdoc9LUEuizoi33f4t6T/WYWfVcJ6+2ng0v18iynU2W6SVfzmK1MbXg/nySqFpMRTo/3ErOZaluSpn8N8PBUsdfqO+XezI/Vq1ZL8mFx2/cBPw/LMrnFH3lc=,iv:RKvjcUc8HSm462LwFGVCQESen6S65XZ2cuazucKWItY=,tag:saZr9DHnKX6hcs2wJdIiOg==,type:str]
lastmodified: "2024-04-10T22:08:45Z"
mac: ENC[AES256_GCM,data:/qNQmTB1qVDzsXqfkrT60/evSLYSp3N2u5dozwTdDcYWckj09UwhxS03HJQvRspmmV+d1g7t1A8VYNEouFqL44IYw0xnbaVnPvSFCR+6Sp2hiFGR90brqRLb6TUmEfvIvIpvsjfHPvvq4pyP1+ap8mubhGsk01vMsAoHNOsEnIQ=,iv:8kmSjECxv8MGwIPAPw2lK+b521vGs3rYrdqhaj3PUpo=,tag:EmQcKMs3K1rqCXiOTNf5TA==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.8.1