Forgejo:
- panel.nix passes the local Forgejo's public, API and ssh URLs (derived
from forgejo.nix) to panel-api.
- Settings dialog: connect a Forgejo access token (verified against
/api/v1/user, stored 0600 in state/panel/forgejo-token).
- New-app dialog gets a Forgejo repository picker with search and a branch
dropdown; private repos are cloned over https with the stored token, or
over ssh with the deploy key when no token is connected. The app name and
domain are filled in from the repository name.
- Commit and compare links in the Source tab point at Forgejo; cards show
the provider ("Forgejo · main").
Git over ssh:
- ssh:// and git@host:owner/repo URLs are accepted; the panel generates an
ed25519 deploy key in state/panel/ssh and uses it for clone/fetch
(BatchMode, accept-new host keys). openssh added to the service path.
- Credential redaction only applies to http(s) URLs, so ssh usernames are
kept; git errors now report the meaningful line instead of git's advice.
Environment variables:
- Stored per app in state/env/<app>.env (0600), outside the repo and stack.
- panelctl passes them to every compose command via env(1), so ${VAR}
interpolation works; by default deploy/restart also generate a compose
override listing the keys under every service's environment (values are
read from compose's environment, never quoted into YAML).
- Environment tab (and a section in the new-app dialog) with .env paste
import, hidden values, validation of names (reserved podman/compose vars
rejected), hints for ${VAR}s the compose file uses but aren't set, and
Save / Save & deploy. Removing an app deletes its variables.
The API still accepts the old source_type "github" / github_* fields.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UbWSNkXxZhYf7eqHTyx3Bf
89 lines
No EOL
2.9 KiB
Nix
89 lines
No EOL
2.9 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
let
|
|
forgejoServer = config.services.forgejo.settings.server;
|
|
in
|
|
{
|
|
environment.systemPackages = [
|
|
(pkgs.writeShellScriptBin "panelctl" (builtins.readFile ./panel/panelctl.sh))
|
|
];
|
|
|
|
users.groups.panelroutes = { };
|
|
|
|
users.users.reudy.extraGroups = [ "panelroutes" ];
|
|
users.users.caddy.extraGroups = [ "panelroutes" ];
|
|
|
|
systemd.tmpfiles.rules = [
|
|
"d /var/lib/containers 0750 reudy panelroutes -"
|
|
"d /var/lib/containers/stacks 0750 reudy panelroutes -"
|
|
"d /var/lib/containers/volumes 0750 reudy panelroutes -"
|
|
"d /var/lib/containers/routes 0750 reudy panelroutes -"
|
|
"d /var/lib/containers/state 0750 reudy panelroutes -"
|
|
"d /var/lib/containers/state/apps 0750 reudy panelroutes -"
|
|
"d /var/lib/containers/backups 0750 reudy panelroutes -"
|
|
"f /var/lib/containers/routes/routes.caddy 0640 reudy panelroutes -"
|
|
];
|
|
|
|
systemd.services.panel-api = {
|
|
description = "Minimal panel API service";
|
|
after = [ "network.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
path = [
|
|
pkgs.podman
|
|
pkgs.podman-compose
|
|
pkgs.curl
|
|
pkgs.coreutils
|
|
pkgs.zip
|
|
pkgs.unzip
|
|
pkgs.git
|
|
pkgs.util-linux # flock, used by panelctl to serialise routes file writes
|
|
pkgs.openssh # cloning repositories over ssh with the panel's deploy key
|
|
];
|
|
|
|
serviceConfig = {
|
|
Type = "simple";
|
|
User = "reudy";
|
|
Group = "panelroutes";
|
|
Restart = "always";
|
|
RestartSec = 3;
|
|
WorkingDirectory = "/var/lib/containers";
|
|
ExecStart = "${pkgs.python3}/bin/python3 ${./panel/panel-api.py}";
|
|
};
|
|
|
|
environment = {
|
|
PANEL_API_BIND = "127.0.0.1";
|
|
PANEL_API_PORT = "9911";
|
|
PANEL_BASE_DIR = "/var/lib/containers";
|
|
PANELCTL_PATH = "/run/current-system/sw/bin/panelctl";
|
|
PANEL_FRONTEND_DIR = "${./panel/frontend}";
|
|
|
|
# Forgejo integration (repo picker, private clones, commit links).
|
|
# The API is reached on localhost; clones use the public URLs.
|
|
PANEL_FORGEJO_URL = lib.removeSuffix "/" forgejoServer.ROOT_URL;
|
|
PANEL_FORGEJO_API_URL = "http://${forgejoServer.HTTP_ADDR}:${toString forgejoServer.HTTP_PORT}";
|
|
PANEL_FORGEJO_SSH_URL = "ssh://${forgejoServer.BUILTIN_SSH_SERVER_USER}@${forgejoServer.DOMAIN}:${toString forgejoServer.SSH_PORT}";
|
|
};
|
|
};
|
|
|
|
services.caddy.virtualHosts."panel.srazka.com".extraConfig = ''
|
|
forward_auth 127.0.0.1:9091 {
|
|
uri /api/authz/forward-auth
|
|
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
|
}
|
|
reverse_proxy 127.0.0.1:9911
|
|
'';
|
|
|
|
systemd.paths."caddy-routes-reload" = {
|
|
wantedBy = [ "multi-user.target" ];
|
|
pathConfig = {
|
|
PathChanged = "/var/lib/containers/routes/routes.caddy";
|
|
};
|
|
};
|
|
|
|
systemd.services."caddy-routes-reload" = {
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
ExecStart = "${pkgs.systemd}/bin/systemctl reload caddy.service";
|
|
};
|
|
};
|
|
} |