anvil-cloud
Cloud infrastructure that's secure by default — not by accident.
Anvil wraps raw cloud resources into opinionated, production-ready components. No boilerplate. No copy-pasting security configs. Just declare what you need.
Built on Pulumi.
Install
pip install anvil-cloud
Secure by default
Every Anvil component ships with defaults aligned to production from day one — public access blocked, encryption enforced, cost tags applied. The goal isn't to make compliance automatic, but to make it a platform you can actually build on.
The App class
Every Anvil program starts with anvil.App(). The run callback receives a Context with:
ctx.stage— current deployment stage (defaults to your OS username for dev isolation)ctx.project— project name fromanvil.yamlctx.export(name, value)— export stack outputsctx.providers— named cloud providers for multi-region / multi-accountctx.ref(id)— reference a resource declared elsewhere (see below)
Forward references (ctx.ref)
Normally you reference a resource through the variable it's assigned to, which
means it must be declared first. ctx.ref("id") lets you reference a resource by
its logical name — even one declared later in the program:
def infra(ctx: anvil.Context):
fn = anvil.aws.Lambda("processor",
runtime=LambdaRuntime.NODEJS20_X,
handler="index.handler",
environment={
# forward reference — `db` is declared below
"DSQL_ENDPOINT": ctx.ref("db").endpoint,
},
)
db = anvil.aws.DSQL("db", schemas=[...])
ctx.ref("db").endpoint resolves to the same output as db.endpoint — they're
interchangeable.
This is an escape hatch for cases where declaration order is awkward; most code references resources directly. Two things to know:
- Keep references flowing one direction. Because you can point either way, you can accidentally create a cycle (A references B's output and B references A's). That deadlocks the deploy rather than erroring cleanly — so don't do it.
- A typo or never-declared id fails with a clear error before anything deploys.
Running locally:
anvil deployuses whateverpython3is on yourPATH, so activate your project venv first (source .venv/bin/activate) or the program can't importpulumi.
Grants
Grants are how Anvil wires permissions between resources. Instead of writing IAM policies by hand, you call .grant() on a resource and Anvil handles both the IAM role policy and the environment variable injection automatically.
A Lambda reading from a Bucket:
import anvil_cloud as anvil
def infra(ctx: anvil.Context):
bucket = anvil.aws.Bucket("uploads",
data_classification="sensitive",
)
fn = anvil.aws.Lambda("processor",
runtime="nodejs20.x",
handler="index.handler",
code="./src",
)
# Grants the Lambda read access to the bucket and scopes down to specific bucket paths.
# Anvil creates the IAM policy and injects UPLOADS_BUCKET_NAME
# into the Lambda's environment automatically.
bucket.grant(fn, actions=["read"], path=["user/*"])
anvil.App(run=infra)
What Anvil does under the hood:
- Creates an IAM
RolePolicyscoped to the exact actions requested - Injects the resource identifier as an environment variable on the target (e.g.
UPLOADS_BUCKET_NAME) - No manual ARN wiring, no forgotten permissions
SvelteKit deployment
Deploy a SvelteKit app to AWS with a single component. Anvil provisions S3, CloudFront, ACM, Lambda (via Lambda Web Adapter), and Route53 — with HTTPS and a custom domain out of the box:
import anvil_cloud as anvil
def infra(ctx: anvil.Context):
site = anvil.aws.SvelteKitSite("web",
domain="myapp.com",
)
ctx.export("url", site.url)
anvil.App(run=infra)
Overrides
Every component accepts a transform argument to override the underlying resource config when you need to break from the defaults:
bucket = anvil.aws.Bucket("custom",
data_classification="non-sensitive",
transform=anvil.aws.BucketTransformArgsArgs(
overrides=anvil.aws.BucketOverridesArgs(
force_destroy=True,
tags={"env": "dev"},
),
),
)
Requirements
- Python >= 3.8
- Pulumi >= 3.0.0
- Anvil CLI:
curl -fsSL https://raw.githubusercontent.com/DamienPace15/anvil/master/install.sh | sh
Links
License
Apache-2.0
Metadata
Release files for anvil-cloud 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| anvil_cloud-0.1.8.tar.gz | 104.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| anvil_cloud-0.1.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 231.2 kB
Release files / anvil_cloud-0.1.8.tar.gz
| Download URL | anvil_cloud-0.1.8.tar.gz |
|---|---|
| Size | 104.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6bab97818faaa0b114e29cdc010d3493e05238f4dfd9d3fe3173e7e4b367b645
|
|
BLAKE2b-256 checksum How to use checksums |
809dd336803f58a22211f9b554b4213174c8965ff8e5a766762e0f5dc4eaf7f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / anvil_cloud-0.1.8-py3-none-any.whl
| Download URL | anvil_cloud-0.1.8-py3-none-any.whl |
|---|---|
| Size | 127.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
292b0d07340e60a214b6a993d2b05056d61fe21c1aff8de352b0d2cd22b702d0
|
|
BLAKE2b-256 checksum How to use checksums |
265b84da24fcb2cda01479777607e4cf6f3daa5071c573d6103567cfd4e060b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|