The aws:storagegateway/gateway:Gateway resource, part of the Pulumi AWS provider, activates and configures a Storage Gateway appliance: its type (file, tape, or volume), network identity, and protocol settings. This guide focuses on three capabilities: gateway type selection, Active Directory integration for SMB, and cached vs stored volume modes.
Storage Gateway requires a running VM appliance (EC2 or on-premises) and network access from Pulumi on port 80 during activation. The examples are intentionally small. Combine them with your own VM infrastructure, cache disk configuration, and maintenance schedules.
Deploy an S3 file gateway for NFS/SMB access
Teams that need to present S3 buckets as network file shares often deploy S3 file gateways, which translate NFS or SMB protocols into S3 API calls.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.storagegateway.Gateway("example", {
gatewayIpAddress: "1.2.3.4",
gatewayName: "example",
gatewayTimezone: "GMT",
gatewayType: "FILE_S3",
});
import pulumi
import pulumi_aws as aws
example = aws.storagegateway.Gateway("example",
gateway_ip_address="1.2.3.4",
gateway_name="example",
gateway_timezone="GMT",
gateway_type="FILE_S3")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/storagegateway"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := storagegateway.NewGateway(ctx, "example", &storagegateway.GatewayArgs{
GatewayIpAddress: pulumi.String("1.2.3.4"),
GatewayName: pulumi.String("example"),
GatewayTimezone: pulumi.String("GMT"),
GatewayType: pulumi.String("FILE_S3"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.StorageGateway.Gateway("example", new()
{
GatewayIpAddress = "1.2.3.4",
GatewayName = "example",
GatewayTimezone = "GMT",
GatewayType = "FILE_S3",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.storagegateway.Gateway;
import com.pulumi.aws.storagegateway.GatewayArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Gateway("example", GatewayArgs.builder()
.gatewayIpAddress("1.2.3.4")
.gatewayName("example")
.gatewayTimezone("GMT")
.gatewayType("FILE_S3")
.build());
}
}
resources:
example:
type: aws:storagegateway:Gateway
properties:
gatewayIpAddress: 1.2.3.4
gatewayName: example
gatewayTimezone: GMT
gatewayType: FILE_S3
The gatewayType property set to FILE_S3 configures the gateway to expose S3 buckets through file protocols. The gatewayIpAddress points to your running Storage Gateway VM; Pulumi connects to this IP on port 80 to retrieve an activation key. The gatewayTimezone affects snapshot scheduling and maintenance windows.
Connect to FSx for Windows with Active Directory
Organizations with FSx for Windows File Server deployments use FSx file gateways to provide low-latency local access to cloud file shares, with Active Directory authentication.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.storagegateway.Gateway("example", {
gatewayIpAddress: "1.2.3.4",
gatewayName: "example",
gatewayTimezone: "GMT",
gatewayType: "FILE_FSX_SMB",
smbActiveDirectorySettings: {
domainName: "corp.example.com",
password: "avoid-plaintext-passwords",
username: "Admin",
},
});
import pulumi
import pulumi_aws as aws
example = aws.storagegateway.Gateway("example",
gateway_ip_address="1.2.3.4",
gateway_name="example",
gateway_timezone="GMT",
gateway_type="FILE_FSX_SMB",
smb_active_directory_settings={
"domain_name": "corp.example.com",
"password": "avoid-plaintext-passwords",
"username": "Admin",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/storagegateway"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := storagegateway.NewGateway(ctx, "example", &storagegateway.GatewayArgs{
GatewayIpAddress: pulumi.String("1.2.3.4"),
GatewayName: pulumi.String("example"),
GatewayTimezone: pulumi.String("GMT"),
GatewayType: pulumi.String("FILE_FSX_SMB"),
SmbActiveDirectorySettings: &storagegateway.GatewaySmbActiveDirectorySettingsArgs{
DomainName: pulumi.String("corp.example.com"),
Password: pulumi.String("avoid-plaintext-passwords"),
Username: pulumi.String("Admin"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.StorageGateway.Gateway("example", new()
{
GatewayIpAddress = "1.2.3.4",
GatewayName = "example",
GatewayTimezone = "GMT",
GatewayType = "FILE_FSX_SMB",
SmbActiveDirectorySettings = new Aws.StorageGateway.Inputs.GatewaySmbActiveDirectorySettingsArgs
{
DomainName = "corp.example.com",
Password = "avoid-plaintext-passwords",
Username = "Admin",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.storagegateway.Gateway;
import com.pulumi.aws.storagegateway.GatewayArgs;
import com.pulumi.aws.storagegateway.inputs.GatewaySmbActiveDirectorySettingsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Gateway("example", GatewayArgs.builder()
.gatewayIpAddress("1.2.3.4")
.gatewayName("example")
.gatewayTimezone("GMT")
.gatewayType("FILE_FSX_SMB")
.smbActiveDirectorySettings(GatewaySmbActiveDirectorySettingsArgs.builder()
.domainName("corp.example.com")
.password("avoid-plaintext-passwords")
.username("Admin")
.build())
.build());
}
}
resources:
example:
type: aws:storagegateway:Gateway
properties:
gatewayIpAddress: 1.2.3.4
gatewayName: example
gatewayTimezone: GMT
gatewayType: FILE_FSX_SMB
smbActiveDirectorySettings:
domainName: corp.example.com
password: avoid-plaintext-passwords
username: Admin
The gatewayType FILE_FSX_SMB enables FSx integration. The smbActiveDirectorySettings block joins the gateway to your Active Directory domain, allowing Windows clients to authenticate with domain credentials. The domainName, username, and password properties establish the domain join; in production, use a secrets manager rather than plaintext passwords.
Archive to virtual tapes for backup software
Backup applications that write to physical tape libraries can target virtual tape libraries instead, storing data in S3 and Glacier without changing backup workflows.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.storagegateway.Gateway("example", {
gatewayIpAddress: "1.2.3.4",
gatewayName: "example",
gatewayTimezone: "GMT",
gatewayType: "VTL",
mediumChangerType: "AWS-Gateway-VTL",
tapeDriveType: "IBM-ULT3580-TD5",
});
import pulumi
import pulumi_aws as aws
example = aws.storagegateway.Gateway("example",
gateway_ip_address="1.2.3.4",
gateway_name="example",
gateway_timezone="GMT",
gateway_type="VTL",
medium_changer_type="AWS-Gateway-VTL",
tape_drive_type="IBM-ULT3580-TD5")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/storagegateway"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := storagegateway.NewGateway(ctx, "example", &storagegateway.GatewayArgs{
GatewayIpAddress: pulumi.String("1.2.3.4"),
GatewayName: pulumi.String("example"),
GatewayTimezone: pulumi.String("GMT"),
GatewayType: pulumi.String("VTL"),
MediumChangerType: pulumi.String("AWS-Gateway-VTL"),
TapeDriveType: pulumi.String("IBM-ULT3580-TD5"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.StorageGateway.Gateway("example", new()
{
GatewayIpAddress = "1.2.3.4",
GatewayName = "example",
GatewayTimezone = "GMT",
GatewayType = "VTL",
MediumChangerType = "AWS-Gateway-VTL",
TapeDriveType = "IBM-ULT3580-TD5",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.storagegateway.Gateway;
import com.pulumi.aws.storagegateway.GatewayArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Gateway("example", GatewayArgs.builder()
.gatewayIpAddress("1.2.3.4")
.gatewayName("example")
.gatewayTimezone("GMT")
.gatewayType("VTL")
.mediumChangerType("AWS-Gateway-VTL")
.tapeDriveType("IBM-ULT3580-TD5")
.build());
}
}
resources:
example:
type: aws:storagegateway:Gateway
properties:
gatewayIpAddress: 1.2.3.4
gatewayName: example
gatewayTimezone: GMT
gatewayType: VTL
mediumChangerType: AWS-Gateway-VTL
tapeDriveType: IBM-ULT3580-TD5
The gatewayType VTL (Virtual Tape Library) emulates physical tape infrastructure. The mediumChangerType and tapeDriveType properties define the virtual hardware your backup software sees; AWS-Gateway-VTL and IBM-ULT3580-TD5 are common choices that work with most backup applications.
Present iSCSI volumes with local cache
Applications that require block storage can use cached volume gateways, which store primary data in S3 while caching frequently accessed data locally for low-latency reads.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.storagegateway.Gateway("example", {
gatewayIpAddress: "1.2.3.4",
gatewayName: "example",
gatewayTimezone: "GMT",
gatewayType: "CACHED",
});
import pulumi
import pulumi_aws as aws
example = aws.storagegateway.Gateway("example",
gateway_ip_address="1.2.3.4",
gateway_name="example",
gateway_timezone="GMT",
gateway_type="CACHED")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/storagegateway"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := storagegateway.NewGateway(ctx, "example", &storagegateway.GatewayArgs{
GatewayIpAddress: pulumi.String("1.2.3.4"),
GatewayName: pulumi.String("example"),
GatewayTimezone: pulumi.String("GMT"),
GatewayType: pulumi.String("CACHED"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.StorageGateway.Gateway("example", new()
{
GatewayIpAddress = "1.2.3.4",
GatewayName = "example",
GatewayTimezone = "GMT",
GatewayType = "CACHED",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.storagegateway.Gateway;
import com.pulumi.aws.storagegateway.GatewayArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Gateway("example", GatewayArgs.builder()
.gatewayIpAddress("1.2.3.4")
.gatewayName("example")
.gatewayTimezone("GMT")
.gatewayType("CACHED")
.build());
}
}
resources:
example:
type: aws:storagegateway:Gateway
properties:
gatewayIpAddress: 1.2.3.4
gatewayName: example
gatewayTimezone: GMT
gatewayType: CACHED
The gatewayType CACHED creates a volume gateway that keeps frequently accessed blocks on local disks while storing the full dataset in S3. This provides low-latency access to hot data without requiring local storage for the entire volume.
Store volumes locally with S3 snapshots
When applications need the entire dataset available locally, stored volume gateways keep all data on-premises while asynchronously backing up point-in-time snapshots to S3.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.storagegateway.Gateway("example", {
gatewayIpAddress: "1.2.3.4",
gatewayName: "example",
gatewayTimezone: "GMT",
gatewayType: "STORED",
});
import pulumi
import pulumi_aws as aws
example = aws.storagegateway.Gateway("example",
gateway_ip_address="1.2.3.4",
gateway_name="example",
gateway_timezone="GMT",
gateway_type="STORED")
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/storagegateway"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := storagegateway.NewGateway(ctx, "example", &storagegateway.GatewayArgs{
GatewayIpAddress: pulumi.String("1.2.3.4"),
GatewayName: pulumi.String("example"),
GatewayTimezone: pulumi.String("GMT"),
GatewayType: pulumi.String("STORED"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.StorageGateway.Gateway("example", new()
{
GatewayIpAddress = "1.2.3.4",
GatewayName = "example",
GatewayTimezone = "GMT",
GatewayType = "STORED",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.storagegateway.Gateway;
import com.pulumi.aws.storagegateway.GatewayArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Gateway("example", GatewayArgs.builder()
.gatewayIpAddress("1.2.3.4")
.gatewayName("example")
.gatewayTimezone("GMT")
.gatewayType("STORED")
.build());
}
}
resources:
example:
type: aws:storagegateway:Gateway
properties:
gatewayIpAddress: 1.2.3.4
gatewayName: example
gatewayTimezone: GMT
gatewayType: STORED
The gatewayType STORED keeps the entire volume on local disks, with asynchronous snapshots to S3. This differs from cached volumes (CACHED) by maintaining full local storage rather than caching subsets. Choose stored volumes when applications require guaranteed local access to all data.
Beyond these examples
These snippets focus on specific gateway-level features: gateway type selection, Active Directory integration for SMB, and tape library emulation. They’re intentionally minimal rather than full storage deployments.
The examples assume pre-existing infrastructure such as a Storage Gateway VM appliance (EC2 instance or on-premises), Active Directory domain (for FSx gateways), and network connectivity from Pulumi to the gateway on port 80. They focus on activating and configuring the gateway rather than provisioning the underlying VM or network.
To keep things focused, common gateway patterns are omitted, including:
- CloudWatch logging configuration (cloudwatchLogGroupArn)
- Maintenance windows (maintenanceStartTime)
- Bandwidth throttling (averageUploadRateLimitInBitsPerSec, averageDownloadRateLimitInBitsPerSec)
- SMB security strategy and guest passwords
- Local cache disk configuration (shown in EX1 but not integrated)
These omissions are intentional: the goal is to illustrate how each gateway type is wired, not provide drop-in storage modules. See the Storage Gateway Gateway resource reference for all available configuration options.
Let's deploy AWS Storage Gateway
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Activation & Connectivity
activationKey if you already have an activation key, or use gatewayIpAddress to retrieve the key automatically. When using gatewayIpAddress, Pulumi must be able to make an HTTP request to port 80 on that IP address.gatewayVpcEndpoint to specify the VPC endpoint address for activation. This requires HTTP access from the computer running Pulumi. Check the VPC Endpoint Security group to ensure required ports are open.Gateway Types & Configuration
Storage Gateway supports five types:
- FILE_S3 - S3 File Gateway
- FILE_FSX_SMB - FSx File Gateway
- VTL - Tape Gateway (Virtual Tape Library)
- CACHED - Volume Gateway (Cached volumes)
- STORED - Volume Gateway (Stored volumes, default)
averageDownloadRateLimitInBitsPerSec and averageUploadRateLimitInBitsPerSec to control bandwidth. These limits are supported for CACHED, STORED, and VTL gateway types.SMB File Share Configuration
smbActiveDirectorySettings with domainName, username, and password. This is only valid for FILE_S3 and FILE_FSX_SMB gateway types and must be set before creating ActiveDirectory authentication SMB file shares.smbGuestPassword before creating GuestAccess authentication SMB file shares. This is only valid for FILE_S3 and FILE_FSX_SMB gateway types. Note that Pulumi can detect whether a guest password exists but not its actual value.ClientSpecified (client chooses), MandatorySigning (requires signing), and MandatoryEncryption (requires encryption). Configure using smbSecurityStrategy.Tape Gateway Configuration
gatewayType to VTL, then specify mediumChangerType (valid values: STK-L700, AWS-Gateway-VTL, IBM-03584L32-0402) and tapeDriveType (valid value: IBM-ULT3580-TD5). Both properties are immutable after creation.Resource Management
activationKey, gatewayIpAddress, gatewayType, gatewayVpcEndpoint, mediumChangerType, and tapeDriveType. Changing any of these requires recreating the gateway.mediumChangerType and tapeDriveType. For smbGuestPassword, it can only detect whether a password exists, not its actual value. For gatewayIpAddress, there’s no API to read the value after creation; use ignoreChanges or omit it from your program after initial creation.activationKey nor gatewayIpAddress is required (the gateway is already activated). When creating a new gateway, you must provide one of these two properties for activation.