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.5
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.5.tar.gz | 103.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| anvil_cloud-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 230.8 kB
Release files / anvil_cloud-0.1.5.tar.gz
| Download URL | anvil_cloud-0.1.5.tar.gz |
|---|---|
| Size | 103.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4e6ec121753c2d6093b4fa9d344516701174484f437004965ee37ea72091533d
|
|
BLAKE2b-256 checksum How to use checksums |
28d4e1ce251a8e5c32d33248916e77f1073f2c94bea47d60e2395d6e9a4beee5
|
| 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.5-py3-none-any.whl
| Download URL | anvil_cloud-0.1.5-py3-none-any.whl |
|---|---|
| Size | 127.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a34c07a2ccb894bf404df18d911178d3933680104da6c76fc61d4a5ee8661b7c
|
|
BLAKE2b-256 checksum How to use checksums |
b37fd44bfdc64a3a2cd4ad29c2639637b012bcfc57d0168eae7f938a296f8285
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|