StelvioApp and stlv_app.py
Every Stelvio project has a stlv_app.py file at its root - this is the
cornerstone of your infrastructure definition. The CLI automatically looks for
this file in your current directory.
Basic Structure
At its simplest, a stlv_app.py only needs a StelvioApp instance and an
@app.run function:
from stelvio.app import StelvioApp
from stelvio.aws.dynamo_db import DynamoTable
from stelvio.aws.function import Function
app = StelvioApp("my-project-name")
@app.run
def run() -> None:
table = DynamoTable(name="users", ...)
fn = Function(handler="functions/users.process", links=[table])
When you need to customize AWS settings, environments, tags, or other options,
add an @app.config function:
from stelvio.app import StelvioApp
from stelvio.config import StelvioAppConfig, AwsConfig
from stelvio.aws.dynamo_db import DynamoTable
from stelvio.aws.function import Function
app = StelvioApp("my-project-name")
@app.config
def configuration(env: str) -> StelvioAppConfig:
return StelvioAppConfig(
aws=AwsConfig(profile="my-profile"),
environments=["staging", "prod"],
)
@app.run
def run() -> None:
table = DynamoTable(name="users", ...)
fn = Function(handler="functions/users.process", links=[table])
Decorators
For Stelvio to load and work properly you need to create a StelvioApp object
with app = StelvioApp("some-name") and define an @app.run function.
The @app.config decorator is optional.
@app.config (optional)
- Purpose: Configures Stelvio for your project and environment
- Parameters:
env: str- the environment name (e.g., "dev", "staging", "prod") - Returns:
StelvioAppConfigobject with AWS settings and other configuration - Timing: Runs first, before any infrastructure is created
When do you need @app.config?
If you don't provide @app.config, Stelvio uses StelvioAppConfig() with
all default values. Add it when you need to:
- Override AWS profile or region
- Define shared environments (e.g.,
["staging", "prod"]) - Set global tags
- Configure DNS providers
- Apply global component customizations
Without @app.config, only personal environments (your username) are valid.
To deploy to named environments like "staging" or "prod", you must define
them via environments in @app.config.
@app.run (required)
- Purpose: Defines your infrastructure components
- Timing: Runs after configuration is loaded
- Requirement: All Stelvio components must be created inside this function ( or in modules when using auto-discovery). See Project Structure for details on component creation order.
Environment-Specific Configuration
You can customize settings based on the environment:
from stelvio.config import AwsConfig, StelvioAppConfig
@app.config
def configuration(env: str) -> StelvioAppConfig:
if env == "prod":
# Production uses separate AWS account
return StelvioAppConfig(
aws=AwsConfig(profile="production-account"),
environments=["staging", "prod"]
)
# Staging/personal use default account
return StelvioAppConfig(environments=["staging", "prod"])
StelvioApp Class
The StelvioApp class is the main entry point for your infrastructure
definition and also defines name of your application.
app = StelvioApp("my-project-name")
Note
The app name is used to identify your infrastructure state. Changing it creates new resources rather than renaming existing ones. See State Management - Renaming for details.
Configuration Options
When using @app.config, the function must return a StelvioAppConfig object.
It supports several configuration options:
AWS Configuration
Both profile and region are optional overrides. When not specified, Stelvio follows the standard AWS credential and region resolution chain.
Basic Usage
@app.config
def configuration(env: str) -> StelvioAppConfig:
# Same as
# StelvioAppConfig(aws=AwsConfig())
# Uses standard AWS credential chain described below
return StelvioAppConfig()
No AWS configuration needed unless you want to override. This uses the standard AWS resolution order for both credentials and region.
Credential Resolution Order
Stelvio uses boto3 and Pulumi, both following the AWS SDK credential chain:
- Explicit profile parameter (override in AwsConfig) - determines which profile's credentials to use
- Environment variables:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN - Assume role providers:
AWS_ROLE_ARN+AWS_WEB_IDENTITY_TOKEN_FILE(OIDC/web identity), or role assumption configured in~/.aws/config - AWS IAM Identity Center (SSO): Configured via
aws sso loginand~/.aws/config - Shared credentials file:
~/.aws/credentials - Shared config file:
~/.aws/config - IAM role credentials (when running in AWS): ECS task role, EC2 instance profile, Lambda execution role
Region Resolution Order
- Explicit
regionparameter (override in AwsConfig) AWS_REGIONorAWS_DEFAULT_REGIONenvironment variable- Region from selected profile in
~/.aws/config - If none specified, AWS operations will fail
Examples
Use environment variables (CI/CD):
# Set in environment: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
@app.config
def configuration(env: str) -> StelvioAppConfig:
return StelvioAppConfig() # Uses env vars automatically
Separate profile for production:
from stelvio.config import AwsConfig
@app.config
def configuration(env: str) -> StelvioAppConfig:
if env == "prod":
# Production uses separate AWS account
return StelvioAppConfig(aws=AwsConfig(profile="production-account"))
# Staging/personal use default account
return StelvioAppConfig()
Use AWS SSO:
aws sso login --profile my-sso-profile
from stelvio.config import AwsConfig
@app.config
def configuration(env: str) -> StelvioAppConfig:
if env=="prod":
profile = "prod-profile"
else:
profile ="my-sso-profile"
return StelvioAppConfig(
aws=AwsConfig(profile=profile)
)
Override region:
from stelvio.config import AwsConfig
@app.config
def configuration(env: str) -> StelvioAppConfig:
return StelvioAppConfig(aws=AwsConfig(region="eu-west-1"))
Environment Validation
@app.config
def configuration(env: str) -> StelvioAppConfig:
return StelvioAppConfig(
environments=["staging", "prod"]
# Only these shared environments allowed
)
With this configuration:
- Anyone can deploy to their personal environment (username)
- Only "staging" and "prod" are accepted as shared environments
- Stelvio will validate environment names and show an error for invalid ones
Common Patterns
Environment-Specific Resources
from stelvio.app import context
...
@app.run
def run() -> None:
env = context().environment
if env == "prod":
# Production-specific resources
prod_only_lambda = Function(name="backup")
# Common resources for all environments
main_table = DynamoTable(name="users", ...)
Next Steps
Now that you understand the StelvioApp structure, you might want to explore:
- Project Structure - Learn about organizing your project files
- Environments - Understand environment management
- Working with Lambda Functions - Create your first Lambda function
- Linking - Connect resources with automatic IAM management