diff --git a/home/apps/ssh.nix b/home/apps/ssh.nix index 0d11e63fe51ed2eb8d3ee31884132bb3d667b8b4..4e849caf7d734b8c9bafbb3e4d00bf412d118e8c 100644 --- a/home/apps/ssh.nix +++ b/home/apps/ssh.nix @@ -73,6 +73,9 @@ Sets up SSH user config. # GitHub github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl + # GitLab (https://docs.gitlab.com/ee/user/gitlab_com/index.html#ssh-known_hosts-entries) + gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf + # FachschaftenGit gitlab.fachschaften.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMK5HFOCvLwU139LPzqW8E1WP8OXj7PcPkIUhqhCLF8l diff --git a/home/desktop/base.nix b/home/desktop/base.nix index e68e4d42ce020057f5a6ea080418b9e2d498ce5a..8d87b9fc36ef360727669b4019e8c0b4bdc13a34 100644 --- a/home/desktop/base.nix +++ b/home/desktop/base.nix @@ -73,7 +73,18 @@ lib.mkIf (!config.eisfunke.headless) { # autostart apps { command = "element-desktop"; } { command = "thunderbird"; } - { command = "vivaldi --class=vivaldi-startup"; } + + /* + Vivaldi supports setting a window class / app_id via `--class`, so I could use an assign + and a special app_id to have a specific Vivaldi window opening in the desired workspace. + + However, this app_id is reused for children windows created by e.g. ctrl+n, which means that + those would also appear in that workspace, even if the parent window is currently somewhere + else, which is annoying. + + So instead, I use this cursed workaround to move the window after startup. + */ + { command = "vivaldi && sleep 3 && swaymsg '[app_id=\"vivaldi-stable\"] move workspace 6'"; } /* I want this repo to be opened on a specific workspace. However, vscode doesn't have a way diff --git a/home/desktop/workspaces.nix b/home/desktop/workspaces.nix index 4eac4b7eb19f748d2ce60299cb186e769e46261e..b9b7201363c860700e1c5c742a0bf175f8e3e0db 100644 --- a/home/desktop/workspaces.nix +++ b/home/desktop/workspaces.nix @@ -41,7 +41,7 @@ "0" = [ { app_id = "YouTube Music"; } ]; "1" = [ { app_id = "Element"; } ]; "2" = [ { app_id = "thunderbird"; } ]; - "6" = [ { app_id = "vivaldi-startup"; } ]; + # some autostarted apps are moved to a workspace by a script instead, see ./base.nix }; }; diff --git a/nixos/extra.nix b/nixos/extra.nix index d116ea47df4b2eb410841138e3780fa9e3b29d72..63a97c207cb14798b7286758a195c0e3287421dd 100644 --- a/nixos/extra.nix +++ b/nixos/extra.nix @@ -4,7 +4,15 @@ misc stuff that's not required for a basic system { pkgs, inputs', lib, config, ... }: -lib.mkIf (!config.eisfunke.minimal) { +let + runscRootless = pkgs.writeShellApplication { + name = "runsc-rootless"; + runtimeInputs = [ pkgs.gvisor ]; + text = '' + exec runsc -ignore-cgroups "$@" + ''; + }; +in lib.mkIf (!config.eisfunke.minimal) { boot.binfmt.emulatedSystems = [ "wasm32-wasi" "wasm64-wasi" @@ -17,9 +25,32 @@ lib.mkIf (!config.eisfunke.minimal) { dns_enabled = true; network_interface = "br-podman"; # bridge device interface name }; + /* + - runs `podman system prune -f` weekly, pruning dangling data + - dangling images: untagged images + - untagged images are created e.g. when pulling a new xyz:latest image + - the previous "latest" image is now untagged, if it's unused it's dangling and will be pruned + - still tagged unused images won't be removed automatically + - manually run `podman system prune --all` for that + */ autoPrune.enable = true; + /* + - gVisor provides an alternative container runtime `runsc` + - provides better isolation + - TODO how + - I use this for GitLab Runner CI containers + - TODO grist + - can be used rootless + - `podman run -it --rm --runtime runsc --runtime-flag ignore-cgroups public.ecr.aws/docker/library/alpine:latest` + - see also https://github.com/google/gvisor/issues/311 + */ + extraPackages = [ + pkgs.gvisor + ]; }; + environment.systemPackages = [ runscRootless ]; + # bluetooth connections can be managed statefully with `bluetoothctl` hardware.bluetooth = { enable = true; diff --git a/nixos/kodi.nix b/nixos/kodi.nix index 431fdd5e3c81b74568757b1d8b89654a99523102..5e81aba3408156d740743abeabd1aefbcb773242 100644 --- a/nixos/kodi.nix +++ b/nixos/kodi.nix @@ -10,9 +10,12 @@ let ]); in lib.mkIf (config.networking.hostName == "amethyst") { # create Kodi user + # TODO oops uid clash users.users.kodi = { isNormalUser = true; extraGroups = [ "video" ]; # for access to HDMI CEC device + uid = 1002; + autoSubUidGidRange = false; # doesn't need them }; services = { diff --git a/nixos/server/age.nix b/nixos/server/age.nix index e77ac12d7ca401bbe46800bed8ef358a55adbe28..f0e7215214230ce71114c7f55e588c55f1ffaae9 100644 --- a/nixos/server/age.nix +++ b/nixos/server/age.nix @@ -259,5 +259,10 @@ Agenix secrets only used in the server config are defined here instead of the to owner = "git"; group = "git"; }; + server-gitlab-runner-podman = { + file = secretsPath + /server/gitlab-runner-podman.age; + owner = "root"; + group = "root"; + }; }; } diff --git a/nixos/server/default.nix b/nixos/server/default.nix index d2eba41a3c2dec7a9fb81ac2354d4d7564bf2008..4ad497ec982cf62afe5ba6ac068685be0652e23b 100644 --- a/nixos/server/default.nix +++ b/nixos/server/default.nix @@ -21,6 +21,7 @@ modules for my services, only used on sapphire, my homeserver ./gallery.nix ./gca4hpx.nix ./git.nix + ./gitlab-runner.nix ./issuebot.nix ./lists.nix ./literature.nix diff --git a/nixos/server/gitlab-runner.nix b/nixos/server/gitlab-runner.nix new file mode 100644 index 0000000000000000000000000000000000000000..2106e5917360a5ce6c01f4fe48df7340f1a1e996 --- /dev/null +++ b/nixos/server/gitlab-runner.nix @@ -0,0 +1,94 @@ +{ lib, config, ... }: + +{ + # https://github.com/NixOS/nixpkgs/blob/c3aa7b8938b17aebd2deecf7be0636000d62a2b9/nixos/modules/services/continuous-integration/gitlab-runner.nix#L730 + /*users = { + users.gitlab-runner = { + group = "gitlab-runner"; + uid = config.ids.uids.gitlab-runner; # TODO was used before dynamicuser + # TODO https://docs.gitlab.com/runner/executors/docker.html#use-podman-to-run-docker-commands + linger = true; + # set subuids/subgids for rootless podman use, hardcode ranges to ensure determinism + subUidRanges = [ + { startUid = 100000; count = 65536; } + ]; + subGidRanges = [ + { startGid = 100000; count = 65536; } + ]; + }; + groups.gitlab-runner.gid = config.ids.gids.gitlab-runner; + };*/ + + systemd.services.gitlab-runner = { + # add the podman socket as prerequisite + after = [ "podman.socket" ]; + requires = [ "podman.socket" ]; + serviceConfig = { + /* + - turning off DynamicUser will run the runner service as root + - so it can use rootful podman for gVisor support + - while `runsc` *can* be used rootless with some workaraounds, I don't do that + - rootless gVisor isn't really documented + - doesn't seem "officially" supported + - can't use cgroups with it + - so for the runners I prefer rootful for "proper" gVisor + */ + #DynamicUser = lib.mkForce false; + #User = lib.mkForce "gitlab-runner"; + #Group = lib.mkForce "gitlab-runner"; + /* + - add the gitlab-runner service to the podman group for access to the socket + - note that similarly to the docker group this is root-equivalent + - I still prefer this over running the unit as root for hardening + */ + SupplementaryGroups = [ "podman" ]; + }; + }; + + environment.persistence."/persist".directories = [ "/var/lib/private/gitlab-runner" ]; + + /* + The gitlab-runner module enables Docker if there are any runners with the docker executor. As I + want to use podman instead, I have to manually force it disabled and set some workaround + options for podman support. + + TODO: PR for gitlab-runner module to support using podman out-of-the-box + */ + virtualisation.docker.enable = lib.mkForce false; + + services.gitlab-runner = { + enable = true; + # give runners some time to finish up on termination of the runner service + gracefulTermination = true; + gracefulTimeout = "1min 30s"; + settings = { + concurrent = 2; # limits concurrent jobs across *all* runners + session_server = { + listen_address = "[::]:61035"; + advertise_address = "[::]:61035"; + }; + }; + services.default = { + # TODO pull always? + description = "sapphire-podman"; + executor = "docker"; + # sets CI_SERVER_URL and CI_SERVER_TOKEN + authenticationTokenConfigFile = config.age.secrets.server-gitlab-runner-podman.path; + dockerImage = "public.ecr.aws/docker/library/alpine:latest"; + registrationFlags = [ + /* + - we can just use the podman socket here + - no need for `virtualisation.dockerSocket.podman.dockerSocket.enable` + - that just symlinks the podman socket at /run/docker.sock + */ + "--docker-host unix:///run/podman/podman.sock" + /* + TODO this is ignored?? + */ + "--docker-runtime runsc" + ]; + #dockerVolumes = [ "/cache" ]; TODO + # seems to be default anyway... + }; + }; +} diff --git a/nixos/users.nix b/nixos/users.nix index 850d3486dd7028e2c8a8b0eb1702f1446d3eacaf..bde0ddd9d5e3ee104fd310649a41712e731f374e 100644 --- a/nixos/users.nix +++ b/nixos/users.nix @@ -12,7 +12,15 @@ config for users and home-manager groups.users.gid = 100; users = { eisfunke = { + # hardcode ids to ensure determinism uid = 1000; + subUidRanges = [ + { startUid = 231072; count = 65536; } + ]; + subGidRanges = [ + { startGid = 231072; count = 65536; } + ]; + description = "Nicolas Lenz"; isNormalUser = true; extraGroups = [ @@ -35,6 +43,14 @@ config for users and home-manager privileges. */ deploy = { + # hardcode ids to ensure determinism + uid = 1001; + subUidRanges = [ + { startUid = 165536; count = 65536; } + ]; + subGidRanges = [ + { startGid = 165536; count = 65536; } + ]; isNormalUser = true; extraGroups = [ "wheel" ]; openssh.authorizedKeys.keys = config.users.users.eisfunke.openssh.authorizedKeys.keys; diff --git a/res/secrets/server/gitlab-runner-podman.age b/res/secrets/server/gitlab-runner-podman.age new file mode 100644 index 0000000000000000000000000000000000000000..14e82e16678b4ec55cb776ad6a2256875496245d Binary files /dev/null and b/res/secrets/server/gitlab-runner-podman.age differ diff --git a/secrets.nix b/secrets.nix index e88b1d46d39b0e5e3e49b1a214f4a0380248c55e..078c935ceaf80eb234df3152763136ee2aa73ea5 100644 --- a/secrets.nix +++ b/secrets.nix @@ -155,6 +155,7 @@ in { "res/secrets/server/gitlab-omni-eisfunkeauth.age".publicKeys = keySets.server; "res/secrets/server/gitlab-pages.age".publicKeys = keySets.server; "res/secrets/server/gitlab-pages-client.age".publicKeys = keySets.server; + "res/secrets/server/gitlab-runner-podman.age".publicKeys = keySets.server; /* Secrets used by the CI runner microvm.