Svix
Overview
This guide covers the deployment and configuration of Svix on Ubuntu 24.04 on Azure using SecureAnyCloud Azure Marketplace images. Svix is the open source webhooks as a service server: a JWT authenticated REST API that sends, signs, queues, retries and manages the outbound webhooks your application delivers to your customers' endpoints. Instead of building and operating a reliable webhook pipeline yourself, you create applications and endpoints and send messages through the API, and Svix handles signing, delivery, exponential backoff retries and delivery observability.
The SecureAnyCloud image ships the free and open source, MIT licensed svix-server (a Rust binary), run the officially supported way as the upstream container pinned by image digest, alongside a bundled PostgreSQL for durable state and Redis for the delivery queue and cache. All three images are pinned by digest and captured into the VM, so your instance starts in seconds. Because Svix is a control plane for outbound events, nothing ships with a known secret: a unique JWT signing secret, a unique database password, a unique Redis password and a unique bootstrap API token are generated for each VM on first boot, before the port is reachable. Backed by 24/7 SecureAnyCloud support.
Svix is a trademark of its respective owner. This image is produced by SecureAnyCloud and is not affiliated with, endorsed by, or sponsored by Svix. It ships the free and open source MIT licensed self hosted software, unmodified.
What is included:
- Svix server v1.98.0 (the MIT licensed svix-server Rust binary), pinned by image digest
- A bundled PostgreSQL 16 database, pinned by image digest, reachable only inside a private Docker network (never published to a host port)
- A bundled Redis 7 queue and cache, pinned by image digest, password protected and reachable only inside the private Docker network
- Docker Engine with the svix API published to the loopback interface only, fronted by nginx on port
80
svix.service,svix-firstboot.service,svix-postboot.serviceandnginx.serviceas systemd units, enabled and active on boot
- A unique JWT signing secret, a unique PostgreSQL password, a unique Redis password and a unique bootstrap API token generated per VM on first boot, never baked into the image
- A clean, empty database on first boot: no default login, no shipped secret, no prior data
- Ubuntu 24.04 LTS base with latest security patches applied at build time
- Azure Linux Agent for seamless cloud integration and SSH key injection
- 24/7 SecureAnyCloud support with guaranteed 24 hour response SLA
Prerequisites
- An active Azure subscription, an SSH public key, and a VNet with a subnet in the target region
- A subscription to the Svix listing on the Azure Marketplace
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is a sensible starting point. For higher webhook volumes, use Standard_D2s_v5 or larger.
In the network security group (NSG), allow inbound 22/tcp from your management network and 80/tcp for the API from the networks that call it.
Deploy from the Azure Portal
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Svix by SecureAnyCloud, and select Create.
On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80). Then select Review + create and Create.
Deploy from the Azure CLI
RG="svix-prod"; LOCATION="eastus"; VM_NAME="svix-01" IMAGE_URN="sac1647283583153:svix-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name svix-vnet --address-prefix 10.100.0.0/16 --subnet-name svix-subnet --subnet-prefix 10.100.1.0/24 az network nsg create -g "$RG" --name svix-nsg az network nsg rule create -g "$RG" --nsg-name svix-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name svix-nsg --name allow-http --priority 110 \
--destination-port-ranges 80 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:svix-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name svix-vnet --subnet svix-subnet --nsg svix-nsg --public-ip-sku StandardConnect to your VM
ssh azureuser@<vm-ip>Confirm the services are running
The stack runs as three containers (svix-server, PostgreSQL and Redis) under one svix.service, fronted by nginx. Confirm that the services are active, list the containers, and check which ports are bound.
nginx listens on :80. The Svix API is published to 127.0.0.1:8071 (loopback only). PostgreSQL and Redis have no host port at all.
sudo systemctl is-active docker svix nginx
sudo docker compose -f /etc/svix/compose.yaml ps
sudo ss -tlnp | grep -E ':80 |:8071'All three services report active and the three containers are running. nginx is bound on :80, and the Svix API is bound only on 127.0.0.1:8071. PostgreSQL (5432) and Redis (6379) never appear on a host port, because they are reachable only inside the private Docker network.
Read the per instance credentials
On first boot, before the port was reachable, this VM generated a unique JWT signing secret, database password, Redis password and bootstrap API token. It wrote them to a root-only file. Read the file:
sudo cat /root/svix-credentials.txtThe file (mode 0600 root:root) holds SVIX_JWT_SECRET, the bootstrap API_TOKEN that you authenticate the API with, POSTGRES_PASSWORD, REDIS_PASSWORD, and SVIX_URL (the address to reach this VM on).
None of these values ship in the image. Every value is unique to this VM, so no two instances share a credential and there is no default token to change.
Verify the API security model
The health endpoint is public, but every other endpoint requires the bearer token. Confirm that an unauthenticated request is rejected with 401, while the per-instance token authenticates a real call:
SVIX_TOKEN=$(sudo grep '^API_TOKEN=' /root/svix-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'health (no auth): %{http_code}\n' http://localhost/api/v1/health/
curl -s -o /dev/null -w 'list apps (no token): %{http_code}\n' http://localhost/api/v1/app/
curl -s -o /dev/null -w 'list apps (with token): %{http_code}\n' -H "Authorization: Bearer $SVIX_TOKEN" http://localhost/api/v1/app/The health check returns 200 with no authentication. The unauthenticated application list is rejected with 401, and the same call with the per-instance token returns 200. This is the whole security model: the health probe is open for load balancers, and the bearer token gates everything else.
Send your first webhook
The core workflow has four parts. Create an application (one per customer or tenant), register the event types you send, add endpoints (the URLs Svix delivers to), then send messages. Svix signs each message, queues it, and delivers it to every matching endpoint, retrying with exponential backoff on failure. Run the whole flow from the VM:
SVIX_TOKEN=$(sudo grep '^API_TOKEN=' /root/svix-credentials.txt | cut -d= -f2-)
APP_ID=$(curl -s -X POST http://localhost/api/v1/app/ \
-H "Authorization: Bearer $SVIX_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"orders-service"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])')
echo "application: $APP_ID" curl -s -X POST http://localhost/api/v1/event-type/ \
-H "Authorization: Bearer $SVIX_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"order.created","description":"An order was created"}' >/dev/null curl -s -X POST http://localhost/api/v1/app/$APP_ID/endpoint/ \
-H "Authorization: Bearer $SVIX_TOKEN" -H 'Content-Type: application/json' \
-d '{"url":"https://example.com/webhook","description":"partner endpoint"}' >/dev/null curl -s -X POST http://localhost/api/v1/app/$APP_ID/msg/ \
-H "Authorization: Bearer $SVIX_TOKEN" -H 'Content-Type: application/json' \
-d '{"eventType":"order.created","payload":{"orderId":"ord_123","amount":4200}}' echoEach call returns the created object as JSON. The final POST .../msg/ returns a message with an id that begins msg_ and your payload echoed back. Svix has accepted the event, signed it, and queued it for delivery to the https://example.com/webhook endpoint with automatic retries.
To see a signed delivery arrive, point the endpoint URL at a real receiver of yours. For a quick test, use a request bin.
Call the API from your own machine
You can call the API from anywhere that can reach the VM on port 80. Use the bootstrap token and the VM public IP. Retrieve the token once over SSH, then call the API with your VM address:
curl -H "Authorization: Bearer <API_TOKEN>" http://<vm-ip>/api/v1/app/In production, use the official Svix client libraries, available for Python, JavaScript/TypeScript, Go, Rust, Java, C#, Ruby, PHP and more. Point the library's server_url at http://<vm-ip>/ (or your own domain, see Step 10) and pass the bootstrap token. You then create applications, endpoints and messages from your application code, exactly as the curl calls above do.
Mint additional API tokens
The bootstrap token is scoped to one organization. To issue additional tokens, for example one per environment or per tenant boundary, generate them with the same per-instance JWT secret:
sudo docker run --rm --env-file /etc/svix/svix.env -e SVIX_QUEUE_TYPE=redis -e SVIX_CACHE_TYPE=redis \
svix/svix-server svix-server jwt generateThe command prints a new Token (Bearer): ... value signed with this VM's JWT secret. Store it securely. Anyone who holds a token can call the API, so treat tokens like passwords. If a token is ever exposed, rotate the JWT secret in /etc/svix/svix.env, then run sudo systemctl restart svix.
Use your own domain and HTTPS (production)
The image serves the API over plain HTTP on port 80, which suits a load balancer or private network. In production, terminate TLS in front of Svix so that tokens and payloads travel encrypted. Choose one option:
- Front the VM with Azure Application Gateway, a load balancer with a managed certificate, or a CDN, and forward to nginx on port
80. - Install your own certificate. Add a TLS
serverblock to/etc/nginx/sites-available/svixthat references your certificate and key, open443/tcpon the NSG, then runsudo systemctl reload nginx.
Then point a DNS name that you control at the VM public IP. Use that name, with https://, as the server_url in your Svix client libraries.
Server components
Component Version / Detail
Webhooks server svix-server v1.98.0 (Rust binary, pinned by image digest)
API front nginx on :80 reverse proxying to 127.0.0.1:8071
Database bundled PostgreSQL 16 (private Docker network, no host port)
Queue and cache bundled Redis 7 (private Docker network, no host port, password protected)
Orchestration Docker Compose under svix.service
JWT secret per instance, generated first boot into /etc/svix/svix.env
Bootstrap token per instance, minted first boot into /root/svix-credentials.txt
Operating system Ubuntu 24.04 LTS (patched at build)
License MIT (Svix)
Managing the Svix service
sudo systemctl status svix --no-pager | head -12 sudo docker compose -f /etc/svix/compose.yaml logs --tail 40 svix-serverRestart the whole stack with sudo systemctl restart svix. Follow the API logs live with sudo docker compose -f /etc/svix/compose.yaml logs -f svix-server. The configuration is in /etc/svix/svix.env and /etc/svix/compose.yaml. After you change the environment file, restart the service to apply the change.
Security recommendations
- Restrict the NSG. Allow TCP 80, and 22 for admin, only from the networks that call the API.
- Terminate TLS in front of Svix (Step 10), so that bearer tokens and payloads are encrypted in transit.
- Treat tokens like passwords. They are stored in
/root/svix-credentials.txt(root only). Rotate the JWT secret if a token is ever exposed. - Keep the bundled database and queue private. PostgreSQL and Redis sit on a private Docker network with no host port. Keep them that way.
- Keep the OS patched. Unattended security upgrades stay enabled on the running VM.
Support and Licensing
Svix is distributed under the MIT License. This SecureAnyCloud image bundles the unmodified official open source svix-server release; SecureAnyCloud provides the packaging, the bundled PostgreSQL and Redis, the per instance secret generation and bootstrap token, the paired deploy guide, and 24/7 support with a guaranteed 24 hour response SLA. Svix is an independent open source project and this image is not affiliated with or endorsed by Svix.
Deploy on Azure
Find Svix on Ubuntu 24.04 on the Azure Marketplace, published by SecureAnyCloud. Deploy from the Portal or the Azure CLI as shown above.
Need Help?
Email sales@secureanycloud.com for deployment help, configuration questions, or licensing enquiries.
Deploy on Azure
Launch Svix on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com