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
CallWhat it does
GET /applications/{uuid}/storages{persistent_storages, file_storages}
POST /applications/{uuid}/storagesAdd a volume (type: persistent, name, mount_path) or a file mount (type: file, mount_path, content)
PATCH /applications/{uuid}/storagesChange 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
  • frequency is a cron expression or hourly, daily, weekly or monthly.
  • stop_during_backup: true stops 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 pass save_s3: true with its s3_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}'
CallWhat it does
GET /hostwolf/servers/{uuid}/volumesThe server's volumes, with size, use, backups and price
GET /hostwolf/servers/{uuid}/volumes/offerSizes allowed in the server's city and the price of size_gb
POST /hostwolf/servers/{uuid}/volumesAdd 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}/detachUnmount and detach it from the server
DELETE /hostwolf/servers/{uuid}/volumes/{id}Delete it and its files
GET /hostwolf/volumesEvery volume of the team; ?status=detached for the detached ones
POST /hostwolf/volumes/{id}/attachAttach 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 the 422 answer has confirm_required: true, a readable message and the price in quote.
  • 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_until shows 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}/restore with backup_id, server_uuid and confirm.
  • 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.

Stuck, or missing an endpoint? Tell us at app.hostwolf.net/contact or [email protected].