S3 Gateway Setup
Enable the Vaulthalla S3 Gateway service and choose direct listener or managed Nginx S3-domain endpoints for downstream S3 clients.
S3 Gateway Setup
Use this page to enable the S3 Gateway service and choose how downstream S3 clients reach Vaulthalla.
Service Commands
The gateway runtime service is named S3GatewayService. Enabling or disabling it updates Vaulthalla config and restarts only the gateway service.
1vh s3-gateway status2vh s3-gateway enable3vh s3-gateway disable
vh s3-gateway status reports the configured endpoint, readiness, and request counters. Disabling the service does not remove gateway credentials, bucket bindings, or budget policies.
Config
The gateway is disabled by default:
1s3_gateway:2 enabled: false3 host: 0.0.0.04 port: 390005 max_connections: 10246 max_body_size_mb: 51207 require_sigv4: true8 allow_path_style: true9 allow_virtual_hosted_style: true10 default_bucket_mode: local11 default_api_exclusive: true12 multipart:13 min_part_size_mb: 514 abort_after_days: 715 synthetic_local_request_cost_usd:16 list: "0.00000001"17 head: "0.00000001"18 get: "0.00000001"19 put: "0.00000001"20 delete: "0.00000001"21 copy: "0.00000001"22 downloaded_gb: "0.00000000"23 uploaded_gb: "0.00000000"
Older configuration files also carry default_remote_sync_strategy and default_remote_conflict_policy here. They were never gateway settings: they are the defaults for new S3/R2 vaults and now live under vaults.s3 (see Configuration). The old keys are still read when the new ones are absent. Remote-cache gateway buckets always use the cache strategy with keep_local.
synthetic_local_request_cost_usd is used only when a gateway credential has enforce_budget_for_local_requests enabled. It gives local/cache requests a tiny nominal cost for gateway key budgets without creating provider, vault, or global upstream usage.
Direct Listener
Use the direct listener for local clients and development:
1aws configure set s3.addressing_style path2aws --endpoint-url http://127.0.0.1:39000 s3api list-buckets
The default local URL is:
1http://127.0.0.1:39000
Keep SigV4 enabled for real client validation. Downstream clients should generally use path-style addressing, especially when they share configuration with the public S3-domain endpoint.
Managed Nginx S3-Domain Endpoint
Managed Nginx can publish the gateway on its own HTTPS hostname, next to the web console:
1sudo vh setup nginx \2 --domain vaulthalla.example.com \3 --s3-domain s3.vaulthalla.example.com \4 --certbot-dns-cloudflare /etc/vaulthalla/certbot/cloudflare.ini
The S3 domain proxies requests to the direct gateway listener and preserves the signed URI. It marks requests as path-style-only so the router does not interpret s3.vaulthalla.example.com as a virtual-hosted bucket.
Why The S3 Domain Needs Cloudflare DNS-01
--s3-domain works only with --certbot-dns-cloudflare <credentials>. --certbot is refused with --s3-domain requires --certbot-dns-cloudflare <credentials> for managed HTTPS routing.
With an S3 domain, Vaulthalla writes both HTTPS server blocks itself, so it needs one certificate that covers both hostnames before Nginx is reloaded. The only certificate mode that issues that certificate is certbot certonly with Certbot's Cloudflare DNS plugin. --certbot hands the HTTPS block to Certbot's Nginx plugin, which edits the site for --domain only and has no S3 host to add.
DNS-01 proves domain ownership by writing a temporary TXT record through the Cloudflare API. Let's Encrypt never connects to the host, so the S3 domain works on LAN, lab, and firewalled hosts that have no inbound port 80. The Cloudflare credentials file is where Certbot gets the API token for those TXT records.
Prerequisites
- Put the DNS zones for both hostnames on Cloudflare. They can be the same zone, as in
vaulthalla.example.comands3.vaulthalla.example.com. - Point both hostnames at the host (
A/AAAArecords, or local DNS for LAN-only hosts). Issuance does not need this, but clients do. - Install the Certbot plugin:
sudo apt install certbot python3-certbot-dns-cloudflare. The package recommends it, so it is usually present already. - Create a Cloudflare API token: in the Cloudflare dashboard, open My Profile → API Tokens → Create Token, choose the Edit zone DNS template, and set Zone Resources to the zone or zones above. The token needs the Zone → DNS → Edit permission. :::
- Put the DNS zones for both hostnames on Cloudflare. They can be the same zone, as in
Create The Credentials File
The file is a Certbot
dns-cloudflarecredentials file. It holds one setting:1# /etc/vaulthalla/certbot/cloudflare.ini2dns_cloudflare_api_token = <your Cloudflare API token>dns_cloudflare_api_tokenis the variable name. Certbot also accepts the legacy pairdns_cloudflare_emailplusdns_cloudflare_api_key(the account-wide Global API Key), but a scoped token is safer. Do not put both forms in the file.Create it root-owned and private, without echoing the token into shell history:
1sudo install -d -m 0700 -o root -g root /etc/vaulthalla/certbot2sudo install -m 0600 -o root -g root /dev/null /etc/vaulthalla/certbot/cloudflare.ini3sudoedit /etc/vaulthalla/certbot/cloudflare.inivh setup nginxrefuses the file if it is missing, is not a regular file, or is readable by group or others. Any path works./etc/vaulthalla/certbot/cloudflare.iniis the convention used in these docs. Pass it as the value of--certbot-dns-cloudflare. The older two-flag form,--certbot-dns-cloudflare --cloudflare-credentials <path>, still works.Leave the file in place after setupCertbot records the credentials path in
/etc/letsencrypt/renewal/<domain>.confand reads it on every renewal. Moving or deleting the file, or revoking the token, makes the next renewal fail. Package purge keeps/etc/vaulthalla/certbot/for this reason.Run Setup
1sudo vh setup nginx \2 --domain vaulthalla.example.com \3 --s3-domain s3.vaulthalla.example.com \4 --certbot-dns-cloudflare /etc/vaulthalla/certbot/cloudflare.iniSetup then:
- requests one certificate named after
--domainthat covers both hostnames, or reuses it when it is current and already covers both; - installs a Certbot deploy hook that reloads Nginx after renewal;
- renders an HTTP to HTTPS redirect for both hostnames, the web console on
--domain, and the S3 gateway on--s3-domain.
The S3 domain is recorded in the managed site, so later runs of
sudo vh setup nginx --certbot-dns-cloudflare <path>keep it without repeating--s3-domain.- requests one certificate named after
Troubleshooting
Message Fix --s3-domain requires --certbot-dns-cloudflare <credentials> for managed HTTPS routingReplace --certbotwith--certbot-dns-cloudflare <path>.--certbot-dns-cloudflare requires the Cloudflare credentials file pathPut the file path right after the flag: --certbot-dns-cloudflare <path>.Cloudflare credentials file must not be group/world accessiblesudo chmod 0600 <path>certbot Cloudflare DNS plugin is not installedsudo apt install python3-certbot-dns-cloudflareCertbot reports Either dns_cloudflare_api_token (recommended), or dns_cloudflare_email and dns_cloudflare_api_key are requiredThe file has no usable setting. Check the variable name and the =.Certbot reports a Cloudflare authentication or zone error The token is wrong, expired, or lacks Zone → DNS → Edit on the zone of one of the hostnames. Path-Style And SigV4
Use path-style URLs for downstream clients:
1https://s3.vaulthalla.example.com/archive/reports/report.pdfThat shape maps
archiveto the gateway bucket andreports/report.pdfto the object key. SigV4 signs the path sent by the client, so reverse proxies must preserve the URI and host behavior expected by the managed S3-domain configuration.Virtual-hosted style may be accepted by the direct listener when enabled, but path-style is the operational default for public reverse-proxy mode.
Web Console Workflow
Use the browser workflow for interactive setup:
- Open S3 gateway (under Storage & cost) in the web console.
- Check service readiness and endpoint information.
- Create a gateway credential.
- Copy the secret immediately; the secret access key is shown only once.
- Choose
user_access,vault_allowlist, orglobalscope. - For
vault_allowlist, choose the key default vault role, select vaults, then add per-vault role or path overrides only for exceptions. - For
global, choose the key default vault role; gateway bucket bindings define the vault set. - Create or bind a gateway bucket.
- Set gateway key or key/vault budgets.
- Copy AWS CLI or MinIO client snippets.
- Use budget status and ledger views to troubleshoot
AccessDeniedorSlowDownresponses.
CLI Workflow
Use the CLI for automation and host-local checks:
1vh s3-gateway status2vh s3-gateway enable3vh s3-gateway disableCredentials:
1vh s3-gateway creds create laptop --json2vh s3-gateway creds list3vh s3-gateway creds revoke VH...4vh s3-gateway creds scope backup show5vh s3-gateway creds scope backup set --scope vault-allowlist6vh s3-gateway creds role assign backup --vault archive --role contributor7vh s3-gateway creds role override add backup --vault archive --pattern "/private/*" --permission download --effect deny8vh s3-gateway creds role override list backup --vault archive9vh s3-gateway creds role revoke backup --vault archiveBoolean scope flags and
creds scope allow-vaultare CLI/API shorthand. Gateway authorization uses selected vaults, default vault roles, role exceptions, and path overrides.Buckets:
1vh s3-gateway bucket list2vh s3-gateway bucket bind photos --vault 12 --mode local3vh s3-gateway bucket create-local archive4vh s3-gateway bucket create-remote-cache edge --api-key r2-main --upstream-bucket origin --encrypt5vh s3-gateway bucket backfill archiveBudgets:
1vh s3-gateway budget set-key backup --monthly 5 --mode enforce --currency USD2vh s3-gateway budget set-key-vault backup --vault archive --monthly 2 --mode enforce3vh s3-gateway budget list --key backup4vh s3-gateway budget disable-key backup5vh s3-gateway budget disable-key-vault backup --vault archive6vh s3-gateway budget status --key backup7vh s3-gateway budget ledger --key backup --limit 50
