From 6b0bc344cecdf595e4f15a2411689cd4d93866df Mon Sep 17 00:00:00 2001 From: jobala Date: Mon, 23 Mar 2026 17:18:22 +0000 Subject: [PATCH] spindle/engine: read secrets from environment file --- nix/vm.nix | 5 +++++ nix/modules/spindle.nix | 21 +++++++++++++++++---- spindle/engine/engine.go | 25 +++++++------------------ spindle/engine/s3.go | 10 +++++++--- 4 file(s) changed, 36 insertion(s)(+), 25 deletion(s)(-) diff --git a/nix/vm.nix b/nix/vm.nix --- a/nix/vm.nix +++ b/nix/vm.nix @@ -118,6 +118,7 @@ }; services.tangled.spindle = { enable = true; + environmentFile = "/var/lib/spindle/.env"; server = { owner = envVar "TANGLED_VM_SPINDLE_OWNER"; hostname = envVarOr "TANGLED_VM_SPINDLE_HOST" "localhost:6555"; @@ -130,6 +131,10 @@ secrets = { provider = "sqlite"; }; + }; + + pipelines = { + logBucket = envVarOr "SPINDLE_S3_LOG_BUCKET" ""; }; }; services.postgresql = { diff --git a/nix/modules/spindle.nix b/nix/modules/spindle.nix --- a/nix/modules/spindle.nix +++ b/nix/modules/spindle.nix @@ -116,6 +116,20 @@ description = "S3 bucket for workflow logs"; }; }; + + environmentFile = mkOption { + type = with types; nullOr path; + default = null; + example = "/etc/spindle.env"; + description = '' + Additional environment file as defined in {manpage}`systemd.exec(5)`. + + Sensitive secrets such as {env}`AWS_SECRET_ACCESS_KEY`, + {env}`AWS_ACCESS_KEY_ID`, {env}`AWS_REGION` + may be passed to the service + without making them world readable in the nix store. + ''; + }; }; }; @@ -129,6 +143,8 @@ serviceConfig = { LogsDirectory = "spindle"; StateDirectory = "spindle"; + EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; + Environment = [ "SPINDLE_SERVER_LISTEN_ADDR=${cfg.server.listenAddr}" "SPINDLE_SERVER_DB_PATH=${cfg.server.dbPath}" @@ -144,10 +160,7 @@ "SPINDLE_SERVER_SECRETS_OPENBAO_MOUNT=${cfg.server.secrets.openbao.mount}" "SPINDLE_NIXERY_PIPELINES_NIXERY=${cfg.pipelines.nixery}" "SPINDLE_NIXERY_PIPELINES_WORKFLOW_TIMEOUT=${cfg.pipelines.workflowTimeout}" - "SPINDLE_NIXERY_PIPELINES_LOG_BUCKET=${cfg.pipelines.logBucket}" - "AWS_ACCESS_KEY_ID=${builtins.getEnv "AWS_ACCESS_KEY_ID"}" - "AWS_SECRET_ACCESS_KEY=${builtins.getEnv "AWS_SECRET_ACCESS_KEY"}" - "AWS_REGION=${builtins.getEnv "AWS_REGION"}" + "SPINDLE_S3_LOG_BUCKET=${cfg.pipelines.logBucket}" ]; ExecStart = "${cfg.package}/bin/spindle"; Restart = "always"; diff --git a/spindle/engine/engine.go b/spindle/engine/engine.go --- a/spindle/engine/engine.go +++ b/spindle/engine/engine.go @@ -37,6 +37,11 @@ secretValues[i] = s.Value } + s3, err := NewS3(cfg.S3.LogBucket) + if err != nil { + l.Error("error creating s3 client", "err", err) + } + var wg sync.WaitGroup for eng, wfs := range pipeline.Workflows { workflowTimeout := eng.WorkflowTimeout() @@ -53,11 +58,9 @@ } defer func() { - logBucket := cfg.S3.LogBucket - - if logBucket != "" { + if s3 != nil { logFile := filepath.Join(cfg.Server.LogDir, fmt.Sprintf("%s.log", wid.String())) - if err := uploadWorkflowLogs(ctx, logFile, "tangled-demo"); err != nil { + if err := s3.WriteFile(ctx, logFile); err != nil { l.Error("error uploading logs", "err", err) } } @@ -143,18 +146,4 @@ wg.Wait() l.Info("all workflows completed") -} - -func uploadWorkflowLogs(ctx context.Context, logfile, bucket string) error { - s3, err := NewS3(bucket) - if err != nil { - return fmt.Errorf("error creating s3 client: %w", err) - } - - name := filepath.Join(logfile) - if err := s3.WriteFile(ctx, name); err != nil { - return fmt.Errorf("error saving logs: %w", err) - } - - return nil } diff --git a/spindle/engine/s3.go b/spindle/engine/s3.go --- a/spindle/engine/s3.go +++ b/spindle/engine/s3.go @@ -17,9 +17,13 @@ client *s3.Client } -const BASE_S3_PATH = "spindle/workflows" +const BaseS3Path = "spindle/workflows" func NewS3(bucket string) (*S3, error) { + if bucket == "" { + return nil, fmt.Errorf("s3 bucket not provided") + } + ctx := context.Background() sdkConfig, err := config.LoadDefaultConfig(ctx) @@ -35,7 +39,7 @@ } func (s *S3) WriteFile(ctx context.Context, path string) error { - s3_key := fmt.Sprintf("%s/%s", BASE_S3_PATH, filepath.Base(path)) + s3Key := fmt.Sprintf("%s/%s", BaseS3Path, filepath.Base(path)) file, err := os.Open(path) if err != nil { @@ -45,7 +49,7 @@ _, err = s.client.PutObject(ctx, &s3.PutObjectInput{ Bucket: &s.bucket, - Key: &s3_key, + Key: &s3Key, Body: file, }) -- tangled.sh