I built this appliance to give VMware Data Services Manager (DSM) a dedicated S3-compatible backup target in my lab. The goal was a repeatable OVA that I could deploy in vSphere, configure through deployment properties, and connect to DSM without rebuilding an object storage server each time.
The result is S3 Storage Appliance 1.0.0: Ubuntu Server 24.04, SeaweedFS 4.48, and NGINX in one VM. It includes the software needed for offline first-boot installation, a separate data disk, and two buckets with separate credentials. This is a lab release.
GitHub repository · Download the OVA, deployment guide, checksum, and qualification manifest
Update: using this S3 server for the PAIS document library
October 21, 2026: I also use my existing S3 endpoint as source storage for the PAIS instance now configured through VCF Automation. This was an additional configuration on the existing server; it does not change the two-bucket defaults or qualification results of the downloadable 1.0.0 OVA.
I created a separate pais-shared-library bucket and separate library-reader and uploader identities. The PAIS identity lists the approved bucket and reads documents; the uploader supplies the documents. DSM system backups, database backups, and logs remain separate from this library. The bucket stores source documents; PAIS indexing creates the retrieval representation separately.
In PAIS, select Data Indexing and Retrieval → Data Sources → Amazon S3 Compatible Store, then supply the HTTPS server URL, library-reader credentials, dedicated bucket, and an optional approved prefix. Keep endpoint CA trust configured in PAIS. A signed workstation S3 listing does not prove that the PAIS runtime can connect.
After the Automation migration, my S3 firewall needed HTTPS from the new VPC’s actual translated source address. I checked the arriving traffic and added the narrow source rule while preserving DSM’s existing access. Do not copy another lab’s subnet or assume the old runtime source still applies. The new PAIS connector validated and its knowledge-base link was recreated. The CPU embedding endpoint returned a 384-dimensional vector, but initial document indexing and retrieval tests were still pending at this update.
What it was built for
DSM system backups and database backups serve different purposes. A system backup protects DSM’s own configuration and state. A managed database backup protects a database and its recovery history. I wanted a single lab endpoint with separate buckets and service identities for those two workflows.
dsm-system: DSM system backup repository.dsm-postgres: intended backup location for managed PostgreSQL databases.
Each identity is scoped to its own bucket. Anonymous access and cross-bucket access are denied. The endpoint uses HTTPS and path-style S3 addressing. Bucket names and region can be changed during deployment.
How the appliance works
DSM system backup → HTTPS :443 → NGINX → SeaweedFS S3 → dsm-system
DSM database backup → HTTPS :443 → NGINX → SeaweedFS S3 → dsm-postgres
↓
Data and storage metadata: /srv/s3SeaweedFS master, volume, filer, and S3 services run under a dedicated account. Their internal listeners bind to loopback; NGINX exposes HTTPS. Object data and SeaweedFS metadata reside on the data disk at /srv/s3. The storage services require that mount, preventing a missing data disk from silently redirecting writes onto the OS disk.
| Component | Default |
| CPU / memory | 4 vCPU / 8 GiB RAM |
| OS disk | 60 GiB |
| Data disk | 500 GiB |
| Client endpoint | HTTPS, TCP 443 |
| Administration | ubuntu account, SSH on TCP 22 |
| S3 region | us-east-1 |
1. Download and verify the OVA
Download S3-Storage-Appliance-1.0.0.ova and its SHA256 file from the release. On Windows, calculate the hash with PowerShell:
Get-FileHash ./S3-Storage-Appliance-1.0.0.ova -Algorithm SHA256The expected SHA256 for version 1.0.0 is:
a17f9ead3724444da9979254620d94d11796e8f891a904b55be6797c482ac6e72. Deploy in vSphere
- Select Deploy OVF Template, choose the OVA, and select the destination compute resource and datastore. Use thin provisioning for the two disks.
- Map VM Network to a port group reachable by DSM and the database workloads that will write backups.
- Set a unique hostname and the masked Password for default user (ubuntu). There is no baked-in password and no mandatory first-login password change.
- Choose DHCP or Static. Static mode requires an address, dotted-decimal netmask, gateway, and DNS servers. NTP properties apply in Static mode; DHCP deployments use Ubuntu’s NTP defaults.
- Set the S3 endpoint DNS name, for example
s3.lab.example.com, and create the matching DNS record. Set the DNS search domain if required, particularly for a unicast internal.localdomain. - Keep or change the region and two bucket names. Restrict SSH administrator and HTTPS S3 client source CIDRs to the networks that need access. Defaults allow private IPv4 ranges.
- Power on the VM and allow initialization to complete.
Supply an SSH public key if you want key-based access. Uncheck Enable SSH password authentication for key-only SSH; the deployment password still applies to the Ubuntu account. Supply at least a password or key so that you can administer the VM. vCenter administrators can access deployment metadata, including supplied passwords.
First boot expects exactly one blank secondary disk of at least 10 GiB and formats it to its full initial size. Increase disk sizes before first boot if needed. Do not attach an existing data disk for automatic initialization, and do not clone an initialized appliance as a new deployment. Import the clean OVA to generate independent identities and keys.
3. Check initialization and retrieve credentials
Log in as ubuntu using the deployment password or SSH key. Ubuntu initialization finishes before S3 initialization:
cloud-init status --wait
sudo systemctl status s3-appliance-initialize
sudo s3-appliance status
sudo /usr/local/sbin/s3-appliance-health
sudo s3-appliance credentialsWait for the initializer to show active (exited) and for the health check to pass. The credentials command displays the endpoint, buckets, and their scoped access keys and secret keys. Keep that output private. Each deployment generates new credentials and TLS keys, which persist across reboot.
4. Prepare TLS trust
The appliance initially generates a unique self-signed certificate for its configured DNS name. For DSM integration, I use a certificate issued by my lab CA. Generate a CSR with the existing appliance key:
sudo s3-appliance csr > s3.csrSubmit the CSR to your CA, requesting a server certificate whose SAN includes the endpoint DNS name. Transfer the issued certificate and issuer CA bundle securely to the appliance, then install them using the existing private key:
sudo s3-appliance install-tls --cert server-chain.pem --key /etc/s3-appliance/tls/s3.key --ca issuer-ca.pemThe helper checks the hostname, certificate chain, and key match before testing and reloading NGINX. DSM must also trust the issuer. For a deliberate self-signed lab deployment, trust the appliance’s public certificate explicitly. Do not disable certificate verification.
DSM’s supported Kubernetes API documents S3 trust through BackupLocation.spec.trustBundle. For a globally trusted custom CA, append the public CA certificate to ca-bundle.crt in the trusted-root-ca ConfigMap in namespace dsm-system, preserving existing certificates. A location-specific trust ConfigMap is another supported option for database backup locations. Use the DSM API kubeconfig and permissions appropriate to your installation; these are DSM S3 trust settings, separate from vCenter certificate bindings. See the official DSM Kubernetes API reference for the trust bundle format and scope.
5. Configure DSM system backups
My initial integration was tested with DSM 9.1.1, build 9.1.1.0100.25777183. Sign in with an account authorized to manage the system backup repository. In DSM’s system backup repository configuration, enter the following values, replacing the example endpoint and generated credentials:
| Setting | Value |
| S3 endpoint | https://s3.lab.example.com |
| Bucket | dsm-system |
| Region | us-east-1 |
| Access key / secret key | The dsm-system identity from the appliance |
| Force path style | Enabled |
| TLS verification | Enabled, with the endpoint certificate chain trusted |
The endpoint is the server URL; enter the bucket in its separate field. Use the region and bucket selected during OVA deployment if you changed the defaults. Save the repository, confirm connectivity, then run or observe the initial system backup. Check DSM’s system backup history and WAL archival status, and review the retention policy and schedule for your lab.
6. Configure managed PostgreSQL backups separately
A working DSM system repository does not automatically configure database backups. With a DSM Admin or another appropriately authorized account, create an S3 database backup location using the same endpoint and region, the dsm-postgres bucket, and its separate credentials. Enable path-style addressing and configure certificate trust for that location. Select the location in the managed PostgreSQL database’s backup configuration and set the required schedule and retention.
Allow HTTPS connectivity from the database backup workers as well as DSM itself. Run a database backup, restore it to an isolated test database, and test point-in-time recovery when that is part of your lab exercise. My initial system backup integration passed; managed PostgreSQL backup, restore, and PITR remain a separate validation step.
What I tested
The OVA passed twenty qualification checks, including fresh DHCP and static deployments in VMware Workstation, an offline first boot on vCenter, supplied-password authentication, SSH key-only mode, independent credentials and TLS keys, signed S3 operations, multipart readback, bucket isolation, missing-data-mount protection, and object and credential persistence across reboots.
On my original lab deployment, DSM completed a full system backup and reported successful WAL archival. Backup manifests and a sample database file were read back from S3. A complete DSM recovery has not yet been tested. The generic OVA qualification and the original DSM integration are separate evidence; a successful backup is not proof of a successful restore.
Troubleshooting and day-to-day operation
- 403 in a browser: expected without signed credentials. A 403 from an authenticated client calls for checking the identity, bucket, region, and path-style setting.
- Certificate errors: check the endpoint DNS name against the SAN, the served chain, and DSM’s S3 trust bundle.
- Timeouts: check DNS and routing from the actual writer, port group mapping, and the appliance’s permitted HTTPS CIDRs.
- Initialization fails: inspect
sudo journalctl -u s3-appliance-initialize --no-pagerand confirm that the secondary disk is blank and unambiguous. - Storage services refuse to start: verify that
/srv/s3is mounted. The mount guard is intentional.
A local health timer runs every fifteen minutes and checks the mount, services, free space, certificate expiry, and anonymous-access denial. External alerts and DSM backup-age monitoring are not configured. Versioning, object lock, and lifecycle expiration are not enabled by default.
This is one VM with one data disk and no object-level redundancy. Keep an independent recovery copy; this protects the data in my lab if the appliance or its datastore fails. For a consistent cold copy, stop NGINX and all SeaweedFS services and copy the entire /srv/s3 filesystem together with configuration, credentials, and TLS material. Volume files alone do not include all the metadata needed for recovery.
Download S3 Storage Appliance 1.0.0 and the deployment guide.
