Compare commits

...

4 commits

Author SHA1 Message Date
cdf2c24dad WIP: hosts: nixos: porthos: migrate to new host
Some checks failed
ci/woodpecker/push/check Pipeline failed
OVH/Kimsufi are deprecating my current server by the end of the year. So
let's migrate to a new host.

This was more painful than initially planned, OVH introduced a change to
their rescue system which messes with the NixOS installation [1].

In the end I used a kexec image [2] to run the installation.

[1]: https://github.com/NixOS/nix/issues/7790
[2]: https://github.com/nix-community/nixos-images
2024-03-09 02:49:52 +01:00
9acadf9926 hosts: nixos: porthos: switch to forgejo
This required a quick rename to migrate from one to the other.
2024-03-09 02:49:52 +01:00
672626c9e7 hosts: nixos: porthos: secrets: add forgejo mail 2024-03-09 02:49:52 +01:00
ba2b7c1333 nixos: services: add forgejo 2024-03-09 02:49:52 +01:00
11 changed files with 226 additions and 48 deletions

View file

@ -3,15 +3,14 @@
{
boot = {
# Use the GRUB 2 boot loader.
loader.grub = {
enable = true;
# Define on which hard drive you want to install Grub.
device = "/dev/disk/by-id/ata-HGST_HUS724020ALA640_PN2181P6J58M1P";
# Use the systemd-boot EFI boot loader.
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
initrd = {
availableKernelModules = [ "uhci_hcd" "ahci" "usbhid" ];
availableKernelModules = [ "ahci" "xhci_pci" "ehci_pci" "usbhid" "sd_mod" ];
kernelModules = [ "dm-snapshot" ];
};

View file

@ -16,11 +16,5 @@
# Set your time zone.
time.timeZone = "Europe/Paris";
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "20.09"; # Did you read the comment?
system.stateVersion = "24.05"; # Did you read the comment?
}

View file

@ -11,9 +11,18 @@
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/boot";
fsType = "vfat";
};
swapDevices = [
{ device = "/dev/disk/by-label/swap"; }
];
powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
my.hardware = {
firmware = {
cpuFlavor = "intel";
};
};
}

View file

@ -3,7 +3,7 @@
SWAP_SIZE=16GiB
parted /dev/sda --script -- \
mklabel msdos \
mklabel gpt \
mkpart primary 512MiB -$SWAP_SIZE \
mkpart primary linux-swap -$SWAP_SIZE 100% \
mkpart ESP fat32 1MiB 512MiB \
@ -11,14 +11,24 @@ parted /dev/sda --script -- \
parted /dev/sdb --script -- \
mklabel gpt \
mkpart primary 0MiB 100%
mkpart primary 0% 100%
parted /dev/sdc --script -- \
mklabel gpt \
mkpart primary 0% 100%
parted /dev/sdd --script -- \
mklabel gpt \
mkpart primary 0% 100%
mkfs.ext4 -L media1 /dev/sda1
mkfs.ext4 -L media2 /dev/sdb1
mkfs.ext4 -L media3 /dev/sdc1
mkfs.ext4 -L media4 /dev/sdd1
pvcreate /dev/sda1
pvcreate /dev/sdb1
vgcreate lvm /dev/sda1 /dev/sdb1
pvcreate /dev/sdc1
pvcreate /dev/sdd1
vgcreate lvm /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
lvcreate -l 100%FREE -n media lvm
mkfs.ext4 -L nixos /dev/mapper/lvm-media
@ -27,17 +37,17 @@ mkfs.fat -F 32 -n boot /dev/sda3
mount /dev/disk/by-label/nixos /mnt
swapon /dev/sda2
mkdir -p /mnt/boot
mount /dev/disk/by-label/boot /mnt/boot
apt install sudo
useradd -m -G sudo setupuser
# shellcheck disable=2117
su setupuser
cat << EOF
# Run the following commands as setup user
curl -L https://nixos.org/nix/install | sh
. $HOME/.nix-profile/etc/profile.d/nix.sh
nix-channel --add https://nixos.org/channels/nixos-20.09 nixpkgs
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
nix profile install nixpkgs#nixos-install-tools
sudo "$(which nixos-generate-config)" --root /mnt
# Change uuids to labels
@ -54,3 +64,6 @@ git crypt unlock
nixos-install --root /mnt --flake '.#<hostname>'
EOF
# shellcheck disable=2117
su setupuser

View file

@ -6,30 +6,17 @@
hostName = "porthos"; # Define your hostname.
domain = "belanyi.fr"; # Define your domain.
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
useDHCP = false;
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
useDHCP = true;
interfaces = {
bond0.useDHCP = true;
bonding_masters.useDHCP = true;
dummy0.useDHCP = true;
erspan0.useDHCP = true;
eth0.useDHCP = true;
eth1.useDHCP = true;
gre0.useDHCP = true;
gretap0.useDHCP = true;
ifb0.useDHCP = true;
ifb1.useDHCP = true;
ip6tnl0.useDHCP = true;
sit0.useDHCP = true;
teql0.useDHCP = true;
tunl0.useDHCP = true;
eno1.useDHCP = true;
eno2.useDHCP = true;
};
};
# Which interface is used to connect to the internet
my.hardware.networking.externalInterface = "eth0";
my.hardware.networking.externalInterface = "eno1";
}

View file

@ -0,0 +1,10 @@
age-encryption.org/v1
-> ssh-ed25519 cKojmg Lhgx43wR8PtAMf5v1eJxKlUBSAoOLdOOn/QaQrwF8zA
jfUCpgNzkHCNTWCqtErDaLMmg1Oy+s9zUra1JLCi+J4
-> ssh-ed25519 jPowng kSeQ/SmMrzd8ByVu3YHWeZyKmqFZvQSBnDunkB8e6wc
WRmnfrV5xcRXA9t0ZXx6YvbRl0sX4PTrw63VVKX4Ei4
--- a+LLM1gP9g1AbUapbeeKaS4cEcRBmPo3MHU2DSWTAds
Ò,FÜÒ6”â⬘ ixÌ<78>°Øe| «
²
ÌÏœ,{† ˆõvª!†‰zÜ$P;ãé©TØÆÉKW
qGô

View file

@ -21,6 +21,11 @@ in
"drone/secret.age".publicKeys = all;
"drone/ssh/private-key.age".publicKeys = all;
"forgejo/mail-password.age" = {
owner = "git";
publicKeys = all;
};
"gitea/mail-password.age" = {
owner = "git";
publicKeys = all;

View file

@ -36,14 +36,14 @@ in
flood = {
enable = true;
};
# Gitea forge
gitea = {
# Forgejo forge
forgejo = {
enable = true;
mail = {
enable = true;
host = "smtp.migadu.com";
user = lib.my.mkMailAddress "gitea" "belanyi.fr";
passwordFile = secrets."gitea/mail-password".path;
user = lib.my.mkMailAddress "forgejo" "belanyi.fr";
passwordFile = secrets."forgejo/mail-password".path;
};
};
# Meta-indexers

View file

@ -10,6 +10,7 @@
./drone
./fail2ban
./flood
./forgejo
./gitea
./grocy
./indexers

View file

@ -0,0 +1,160 @@
# A low-ressource, full-featured git forge.
{ config, lib, ... }:
let
cfg = config.my.services.forgejo;
in
{
options.my.services.forgejo = with lib; {
enable = mkEnableOption "Forgejo";
port = mkOption {
type = types.port;
default = 3042;
example = 8080;
description = "Internal port";
};
mail = {
enable = mkEnableOption {
description = "mailer configuration";
};
host = mkOption {
type = types.str;
example = "smtp.example.com";
description = "Host for the mail account";
};
port = mkOption {
type = types.port;
default = 465;
example = 587;
description = "Port for the mail account";
};
user = mkOption {
type = types.str;
example = "forgejo@example.com";
description = "User for the mail account";
};
passwordFile = mkOption {
type = types.str;
example = "/run/secrets/forgejo-mail-password.txt";
description = "Password for the mail account";
};
protocol = mkOption {
type = types.str;
default = "smtps";
example = "smtp";
description = "Protocol for connection";
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = cfg.enable -> !config.my.services.gitea.enable;
message = ''
`config.my.services.forgejo` is incompatible with
`config.my.services.gitea`.
'';
}
];
services.forgejo =
let
inherit (config.networking) domain;
forgejoDomain = "git.${domain}";
in
{
enable = true;
appName = "Ambroisie's forge";
user = "git";
group = "git";
lfs.enable = true;
useWizard = false;
database = {
type = "postgres"; # Automatic setup
user = "git"; # User needs to be the same as forgejo user
name = "git"; # Name must be the same as user for `ensureDBOwnership`
};
# NixOS module uses `forgejo dump` to backup repositories and the database,
# but it produces a single .zip file that's not very backup friendly.
# I configure my backup system manually below.
dump.enable = false;
mailerPasswordFile = lib.mkIf cfg.mail.enable cfg.mail.passwordFile;
settings = {
server = {
HTTP_PORT = cfg.port;
DOMAIN = forgejoDomain;
ROOT_URL = "https://${forgejoDomain}";
};
mailer = lib.mkIf cfg.mail.enable {
ENABLED = true;
SMTP_ADDR = cfg.mail.host;
SMTP_PORT = cfg.mail.port;
FROM = "Forgejo <${cfg.mail.user}>";
USER = cfg.mail.user;
PROTOCOL = cfg.mail.protocol;
};
service = {
DISABLE_REGISTRATION = true;
};
session = {
# only send cookies via HTTPS
COOKIE_SECURE = true;
};
};
};
users.users.git = {
description = "Forgejo Service";
home = config.services.forgejo.stateDir;
useDefaultShell = true;
group = "git";
isSystemUser = true;
};
users.groups.git = { };
my.services.nginx.virtualHosts = {
# Proxy to Forgejo
git = {
inherit (cfg) port;
};
# Redirect `forgejo.` to actual forge subdomain
forgejo = {
redirect = config.services.forgejo.settings.server.ROOT_URL;
};
};
my.services.backup = {
paths = [
config.services.forgejo.lfs.contentDir
config.services.forgejo.repositoryRoot
];
};
services.fail2ban.jails = {
forgejo = ''
enabled = true
filter = forgejo
action = iptables-allports
'';
};
environment.etc = {
"fail2ban/filter.d/forgejo.conf".text = ''
[Definition]
failregex = ^.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>$
journalmatch = _SYSTEMD_UNIT=forgejo.service
'';
};
};
}

View file

@ -13,7 +13,7 @@ let
porthos = {
clientNum = 1;
publicKey = "PLdgsizztddri0LYtjuNHr5r2E8D+yI+gM8cm5WDfHQ=";
externalIp = "91.121.177.163";
externalIp = "37.187.146.15";
};
# "Clients"