Skip to content

cachix/cloud.devenv.sh

Repository files navigation

cloud.devenv.sh

A cloud-hosted platform that provides GitHub Actions experience using Nix and devenv.

See talk What if GitHub Actions were local-first and built using Nix?.

Status

Currently in development, sign up for private beta.

Example

On top of regular devenv.sh each CI jobs gets extra information:

{ pkgs, lib, config, ... }:
let
  # https://devenv.sh/cloud/
  github = config.cloud.ci.github;
in {
  # https://devenv.sh/basics/
  packages = [ pkgs.cargo-watch ];

  # https://devenv.sh/languages/
  languages = {
    rust.enable = true;
    python = {
      enable = true;
      venv.enable = true;
      uv.enable = true;
    };
  };

  # https://devenv.sh/processes/
  processes = {
    myapp.exec = "cargo run -x";
  };

  # https://devenv.sh/services/
  services = {
    # run postgresql only locally
    postgresql.enable = !config.cloud.enable;
  };

  # https://devenv.sh/git-hooks/
  git-hooks = {
    hooks.rustfmt.enable = true;
    # run pre-commit hooks only on changes
    fromRef = github.base_ref or null;
    toRef = github.ref or null;
  };

  # https://devenv.sh/tasks/
  tasks = {
    "myapp:tests" = {
      after = [ "devenv:enterTest" ];
      exec = "cargo test";
    };
    # run code review agent on main branch
    "myapp:code-reviewer" = lib.mkIf (github.branch == "main") {
      exec = "claude @code-reviewer";
    };
  };

  # https://devenv.sh/outputs/
  outputs = {
    # package Rust app using Nix
    myapp = config.language.rust.import ./. {};
  };
}

Architecture

  • Backend (Rust) - REST API server handling authentication, project management, and GitHub webhooks
  • Frontend (Elm) - Modern web interface built with elm-land for managing environments
  • Runner (Rust) - WebSocket-connected service for executing commands in remote environments
  • Logger (Rust) - Centralized logging service for collecting and managing logs
  • Database (PostgreSQL 17) - Persistent storage with Diesel ORM migrations
  • Authentication (Zitadel) - Open Source OIDC SSO with OAuth2/LDAP/SAML2/OTP support

Development

  1. Setup Tailscale
  1. Create GitHub App:
  • Name: Choose a unique name for your app (this will be used in config as app_name)
  • Callback URLs:
    • Legacy zitadel login http://localhost:9500/ui/login/login/externalidp/callback
    • V2 login UI http://localhost:9500/idps/callback
  • Permissions: Repository: Check (write), Contents (Read)
  • Account permissions: read only emails
  • Subscribe to events: Pull Request, Check run, Push
  • Webhook URL: BASE_URL/api/v1/github/webhook
  • Secret: generate secure secret (use this as webhook_secret in config)
  1. In the GitHub app's general settings:

    • Generate a new private key (use this in config as app_private_key)
    • Generate a new client secret
    • Save the client ID and client secret to .env.
    export TF_VAR_github_client_id=...
    export TF_VAR_github_client_secret=...
    export TF_VAR_redirect_uris=["http://localhost:1234/", "<BASE_URL>/"]
  2. Create ./cloud.devenv.toml:

base_url = "https://<device-name>.<tailnet-name>.ts.net"

[github]
app_name = "your-app-name" # The name of your GitHub app
  1. Configure development secrets using secretspec:

    secretspec set --provider env GITHUB_APP_PRIVATE_KEY="$(cat path/to/private-key.pem)"
    secretspec set --provider env GITHUB_WEBHOOK_SECRET="your-webhook-secret"
  2. Launch the processes

    devenv up
  3. Initialize Zitadel by following terraform/zitadel/README.md

  4. Set the Zitadel webhook signing key:

    secretspec set --provider env ZITADEL_WEBHOOK_SIGNING_KEY="$(cat .devenv/state/zitadel/signing-key.txt)"

Migrations

diesel migration generate initial --diff-schema
cargo run -p devenv-backend migrate

Production

  1. Generate PostHog API key

  2. Configure production secrets using secretspec:

# Required production secrets
secretspec set --provider vault SENTRY_DSN="your-sentry-dsn"
secretspec set --provider vault POSTHOG_API_KEY="your-posthog-api-key"
secretspec set --provider vault DATABASE_URL="your-production-db-url"
secretspec set --provider vault GITHUB_APP_PRIVATE_KEY="$(cat path/to/private-key.pem)"
secretspec set --provider vault GITHUB_WEBHOOK_SECRET="your-webhook-secret"

About

What if GitHub Actions were local-first and built using Nix?

Topics

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •