DevelopersVolumes and traffic
Volumes, storage and traffic
Persistent volumes#
A container's own files are replaced on every deploy. Anything your app must keep, such as uploads or a SQLite file, goes on a volume mounted into the container.
hw $API/applications/$APP/storages | jq
hw -X POST $API/applications/$APP/storages -d '{"type": "persistent", "name": "uploads", "mount_path": "/app/uploads"}'
hw -X POST $API/applications/$APP/start # mounts it
| Call | What it does |
|---|---|
GET /applications/{uuid}/storages | {persistent_storages, file_storages} |
POST /applications/{uuid}/storages | Add a volume (type: persistent, name, mount_path) or a file mount (type: file, mount_path, content) |
PATCH /applications/{uuid}/storages | Change one (by uuid) |
DELETE /applications/{uuid}/storages/{storage_uuid} | Delete it and its data |
File mounts put a file you supply (a config file, for example) at mount_path. A volume lives on one server: with several copies, each server has its own. Data every copy must see belongs in a managed database.
Volume backups#
Back up a volume on a schedule, and keep a number of archives on the server:
hw -X PUT $API/applications/$APP/storages/$VOLUME/backups -d '{"frequency": "0 3 * * *", "retention_amount_locally": 7}'
hw -X POST $API/applications/$APP/storages/$VOLUME/backups/run # one now
hw -X DELETE $API/applications/$APP/storages/$VOLUME/backups # schedule and archives
frequencyis a cron expression orhourly,daily,weeklyormonthly.stop_during_backup: truestops the app while the volume is archived, for a consistent copy of files in use.- To keep archives off the server too, add an S3-compatible bucket (
POST /s3-storages) and passsave_s3: truewith itss3_storage_uuid.
Storage volumes#
When a server's own disk is too small, add a storage volume to it: 10 to 1000 GB of block storage, mounted at /mnt/volume-<id> on the server, billed by the hour on the server's subscription. Point an app's volume (host_path) or a database dump at that path.
SRV=$(hw $API/hostwolf/servers | jq -r '[.[] | select(.status == "ready")][0].uuid') # a ready purchased server (app server or VPS)
hw "$API/hostwolf/servers/$SRV/volumes/offer?size_gb=50" | jq # sizes allowed in its city and the price
# Without "confirm": true nothing is bought; the 422 answer has the price.
hw -X POST $API/hostwolf/servers/$SRV/volumes -H "Idempotency-Key: $(uuidgen)" -d '{"size_gb": 50, "backups": true, "autogrow_max_gb": 200, "confirm": true}'
hw $API/hostwolf/servers/$SRV/volumes | jq '.[] | {id, status, size_gb, mount_path, monthly_price}'
| Call | What it does |
|---|---|
GET /hostwolf/servers/{uuid}/volumes | The server's volumes, with size, use, backups and price |
GET /hostwolf/servers/{uuid}/volumes/offer | Sizes allowed in the server's city and the price of size_gb |
POST /hostwolf/servers/{uuid}/volumes | Add one (size_gb, backups, autogrow_max_gb, confirm) |
PATCH /hostwolf/servers/{uuid}/volumes/{id} | Enlarge it (size_gb), turn backups on or off, set the auto-grow limit |
POST /hostwolf/servers/{uuid}/volumes/{id}/detach | Unmount and detach it from the server |
DELETE /hostwolf/servers/{uuid}/volumes/{id} | Delete it and its files |
GET /hostwolf/volumes | Every volume of the team; ?status=detached for the detached ones |
POST /hostwolf/volumes/{id}/attach | Attach a detached volume to a server in the same city (server_uuid, confirm) |
- Price: set by the city's provider, through the catalog. In Vultr cities a volume costs $1.24 a month for 10 GB, $3.11 for 25 GB and $12.38 for 100 GB, billed by the hour (monthly ÷ 730).
- Confirm: a new volume, a bigger size, turning backups on and an auto-grow limit raise the bill, so they need
"confirm": true. Without it nothing changes, and the422answer hasconfirm_required: true, a readablemessageand the price inquote. - Enlarging happens online: the file system grows with it and nothing stops. Volumes can't shrink; add a smaller one and delete the old one instead.
- Volume changes are limited to 10 a minute, together with the console's buttons.
Auto-grow#
Set autogrow_max_gb and the volume grows by itself when it is 85% full: by 25%, at least 10 GB, up to your limit. The file system grows online and the new size is billed from then. 0 turns it off.
Backups#
Nightly backups are on by default. They are encrypted, stored off-site in Amsterdam and kept for 7 days. You pay for the space they use: $0.23 a month for 10 GB stored, $2.23 for 100 GB.
hw $API/hostwolf/volumes/$VOL/backups | jq # newest first
hw -X POST $API/hostwolf/servers/$SRV/volumes/$VOL/backups # one now
hw -X POST $API/hostwolf/servers/$SRV/volumes/$VOL/restore -d '{"backup_id": "4f1c2a9b", "target": "new", "confirm": true}'
target: "same"restores into the volume itself: files written after the backup are removed, and the volume is unavailable until the restore is done.target: "new"restores into a new volume of the same size on the same server, billed like any volume.PATCH … {"backups": false}turns them off; the existing backups are deleted after 7 days.
Detach, attach and the 7-day grace period#
- Detach (
POST …/detach) unmounts a volume and takes it off its server. It keeps its files and stays billed until you attach it again or delete it. Stop whatever writes to it first. - When a server is deleted, its volumes are detached and kept for 7 days, free of charge.
kept_untilshows the date; after it, the volume and its files are deleted. - Attach a detached volume to any of your ready servers in the same city with
POST /hostwolf/volumes/{id}/attach. It is mounted at the same path in about a minute. A volume of a deleted server is billed again from then, so that needs"confirm": true. - A detached volume's backups can be restored into a new volume on another server in the same city:
POST /hostwolf/volumes/{id}/restorewithbackup_id,server_uuidandconfirm. DELETE /hostwolf/volumes/{id}deletes a detached volume now.
Traffic#
Each server includes 1 TB of outbound traffic a month. Beyond that, each GB costs $0.01, added to that server's invoice. Inbound traffic is free.
hw $API/hostwolf/servers/$SRV/traffic | jq
# {"month": "2026-10", "outbound_bytes": 12400000000, "outbound": "12.4 GB", "included_bytes": 1000000000000,
# "overage_bytes": 0, "price_per_gb": 0.01, "bill_so_far": 0, "sampled_at": "…"}
hw "$API/hostwolf/traffic?month=2026-09" | jq '.bill_so_far, .servers[].outbound' # every server, any month
Traffic is read every 10 minutes. The Analytics page in the console shows requests per app.
Port 25 (outbound email) is blocked on every server; send email through a provider's API or port 587.