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?.
Currently in development, sign up for private beta.
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 ./. {};
};
}
tailscale up
base_urlAdd export BASE_URL=... to .env
Create GitHub App:
Name: Choose a unique name for your app (this will be used in config as app_name)
http://localhost:9500/ui/login/login/externalidp/callbackhttp://localhost:9500/idps/callbackSecret: generate secure secret (use this as webhook_secret in config)
In the GitHub app's general settings:
app_private_key).env.shell
export TF_VAR_github_client_id=...
export TF_VAR_github_client_secret=...
export TF_VAR_redirect_uris=["http://localhost:1234/", "<BASE_URL>/"]
./cloud.devenv.toml:base_url = "https://<device-name>.<tailnet-name>.ts.net"
[github]
app_name = "your-app-name" # The name of your GitHub app
shell
secretspec set --provider env GITHUB_APP_PRIVATE_KEY="$(cat path/to/private-key.pem)"
secretspec set --provider env GITHUB_WEBHOOK_SECRET="your-webhook-secret"
console
devenv up
Initialize Zitadel by following terraform/zitadel/README.md
Set the Zitadel webhook signing key:
shell
secretspec set --provider env ZITADEL_WEBHOOK_SIGNING_KEY="$(cat .devenv/state/zitadel/signing-key.txt)"
diesel migration generate initial --diff-schema
cargo run -p devenv-backend migrate
Generate PostHog API key
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"
$ claude mcp add cloud.devenv.sh \
-- python -m otcore.mcp_server <graph>