← notes
NOTE

forgejo service as declarative nix code

Updated

I wish more people understood that with nix and nixos modules, you can do some IaaC stuff which declares how a service should run on an existing machine, including its package, system user, database, bind address, ports, public url, and application settings. Nixos evaluates a declarative host configuration into a buildable system generation, with generation-based upgrades and rollbacks. Here is an example of my forgejo module small snippet from my personal multi-node clan codebase that I vibecoded back then and refined through a lot of iterative changes of course (˶˃𐃷˂˶)

The surrounding module still defines the git user and group, forgejoLtsPackage, and values such as settings and effectiveRootUrl.

            # Forgejo + OpenSSH + Caddy
            services = {
              # Forgejo service - run as git user for SSH compatibility
              forgejo = {
                enable = true;
                package = forgejoLtsPackage;
                user = "git";
                group = "git";
                database.type = "sqlite3";
                settings = {
                  DEFAULT = {
                    APP_NAME = "0xrsydn";
                    APP_SLOGAN = "Code";
                  };
                  server = {
                    DOMAIN = settings.domain;
                    ROOT_URL = effectiveRootUrl;
                    HTTP_ADDR = forgejoHttpAddress;
                    HTTP_PORT = forgejoHttpPort;
                    SSH_DOMAIN = settings.domain;
                    SSH_PORT = settings.sshPort;
                    # Production uses OpenSSH. Tailnet staging uses Forgejo's
                    # built-in listener to avoid changing the host SSH service.
                    START_SSH_SERVER = tailnetOnly;
                    DISABLE_SSH = false;
                    LANDING_PAGE = "/0xrsydn";
                  }
                  // lib.optionalAttrs tailnetOnly {
                    SSH_LISTEN_HOST = settings.listenAddress;
                    SSH_LISTEN_PORT = settings.sshPort;
                  };
                  repository = {
                    DISABLE_STARS = true;
                    DISABLE_FORKS = true;
                  }
                  // lib.optionalAttrs settings.staging {
                    DISABLE_MIGRATIONS = true;
                  };
                  service = {
                    DISABLE_REGISTRATION = true;
                    SHOW_REGISTRATION_BUTTON = false;
                  };
                  "service.explore" = {
                    # Caddy protects the HTML explore routes. Keep this false
                    # so anonymous public metadata API requests still work.
                    REQUIRE_SIGNIN_VIEW = false;
                  };
                  actions = {
                    ENABLED = true;
                    # Resolve actions/checkout and other relative references
                    # against Forgejo's maintained action mirror, not GitHub.
                    DEFAULT_ACTIONS_URL = "https://data.forgejo.org";
                  };
                  security = lib.optionalAttrs settings.staging {
                    DISABLE_WEBHOOKS = true;
                  };
                  mirror = lib.optionalAttrs settings.staging {
                    ENABLED = false;
                  };
                  mailer = lib.optionalAttrs settings.staging {
                    ENABLED = false;
                  };
                  ui = {
                    THEMES = "forgejo-auto,forgejo-light,forgejo-dark,dracula,catppuccin-mocha,catppuccin-mocha-minimal";
                    DEFAULT_THEME = "dracula";
                  };
                  "ui.meta" = {
                    AUTHOR = "0xrsydn";
                    DESCRIPTION = "Public code and infrastructure projects by 0xrsydn.";
                    KEYWORDS = "0xrsydn,git,code,infrastructure";
                  };
                  log = {
                    LEVEL = "Info";
                  };
                };
              };
            };

With this, you can verify that your service or app configuration evaluates and builds before deploying it to a machine. nix flake check verifies that the flake evaluates, including the shape of nixosConfigurations, and builds derivations declared under checks, but it doesn’t necessarily build every nixos system closure unless its declared on flake.nix properly. For a build-only check, use nixos-rebuild build --flake .#<machine> or nix build .#nixosConfigurations.<machine>.config.system.build.toplevel. If your pinned clan cli provides clan machines build <machine>, you can use that too then use clan machines update <machine> as the deployment command.

keyboard shortcuts

Desktop keyboard only. Some actions apply to articles.

j / k
scroll down / up
gg / G
top / bottom
g h
home
g a
about
g p
projects
g b
blog
g n
notes
[ h / ] h
previous / next heading
[ p / ] p
older / newer post
?
show this help