unsandbox.com
Anonymous remote code, compile, & execution API for humans & machine learning agents.
Docs 📚 View Pricing →December 21, 2025
Persistent Services: Deploy Web Apps with Automatic HTTPS
Sessions are great for interactive work, but what if you need something that stays running? A webhook receiver. A demo app. A quick API endpoint. Something you can share with a URL.
Today we’re deep-diving into unsandbox Services - persistent containers with automatic HTTPS and custom domain support.
From Sessions to Services
Sessions are ephemeral by design - they exist while you’re connected. But sometimes you need the opposite: something that keeps running after you disconnect.
Sessions: Connect → Work → Disconnect → Container destroyed
Services: Create → Runs forever → Accessible via HTTPS
Services are the “set it and forget it” option. They run in isolated containers just like sessions, but with a key difference: they get a public HTTPS URL.
Creating Your First Service
Let’s deploy a simple Python web server:
un service --name myapi --ports 8000 -n semitrusted \
--bootstrap 'python3 -m http.server 8000'
That’s it. In about 30 seconds you’ll have:
- A running container with your server
-
An HTTPS URL:
https://myapi.svc.unsandbox.com - Automatic SSL certificate (via Let’s Encrypt)
- Traffic proxied to port 8000 inside your container
Service created successfully
ID: unsb-service-abc123def456
Name: myapi
URL: https://myapi.svc.unsandbox.com
Status: running
Open that URL in your browser - you’ll see the directory listing from Python’s HTTP server.
Real-World Example: A Webhook Receiver
Let’s build something more useful. Say you need to receive webhooks from Stripe, GitHub, or any external service. You need:
- A public HTTPS endpoint (webhooks require HTTPS)
- Something to log incoming requests
- A way to inspect what was received
Here’s a simple Flask webhook receiver:
# Create a bootstrap script
cat > /tmp/webhook-server.sh << 'EOF'
#!/bin/bash
pip install flask
cat > /app/server.py << 'PYTHON'
from flask import Flask, request, jsonify
import json
from datetime import datetime
app = Flask(__name__)
webhooks = []
@app.route('/webhook', methods=['POST'])
def receive_webhook():
data = {
'timestamp': datetime.now().isoformat(),
'headers': dict(request.headers),
'body': request.get_json(force=True, silent=True) or request.data.decode()
}
webhooks.append(data)
print(f"Received webhook: {json.dumps(data, indent=2)}")
return jsonify({'status': 'received'}), 200
@app.route('/webhooks', methods=['GET'])
def list_webhooks():
return jsonify(webhooks)
@app.route('/health', methods=['GET'])
def health():
return jsonify({'status': 'ok', 'count': len(webhooks)})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
PYTHON
mkdir -p /app
python3 /app/server.py
EOF
# Deploy it
un service --name webhooks --ports 8000 -n semitrusted \
--bootstrap /tmp/webhook-server.sh
Now you have:
-
https://webhooks.svc.unsandbox.com/webhook- POST webhooks here -
https://webhooks.svc.unsandbox.com/webhooks- GET to see received webhooks -
https://webhooks.svc.unsandbox.com/health- Health check
Test it:
# Send a test webhook
curl -X POST https://webhooks.svc.unsandbox.com/webhook \
-H "Content-Type: application/json" \
-d '{"event": "test", "data": {"message": "hello"}}'
# Check what was received
curl https://webhooks.svc.unsandbox.com/webhooks | jq
Point your Stripe/GitHub/etc webhook settings at https://webhooks.svc.unsandbox.com/webhook and you’re ready to debug.
Custom Domains
Don’t want to use *.svc.unsandbox.com? Bring your own domain:
un service --name blog --ports 8000 -n semitrusted \
--domains blog.example.com,www.example.com \
--bootstrap './start-blog.sh'
Setup:
-
Add a CNAME record:
blog.example.com → svc.unsandbox.com - We’ll automatically provision an SSL certificate
-
Your service is live at
https://blog.example.com
Multiple domains work too - great for www and naked domain handling.
Managing Services
List All Services
$ un service --list
Services: 3
SERVICE ID NAME STATUS PORTS
unsb-service-abc123 webhooks running 8000
unsb-service-def456 myapi sleeping 8000
unsb-service-ghi789 demo running 3000,8080
Check Service Details
$ un service --info webhooks
Service: webhooks
ID: unsb-service-abc123def456
Status: running
Ports: 8000
URL: https://webhooks.svc.unsandbox.com
Created: 2025-12-21 10:30:00 UTC
Last Activity: 2025-12-21 14:22:15 UTC
View Bootstrap Logs
$ un service --logs webhooks
[2025-12-21 10:30:05] Installing flask...
[2025-12-21 10:30:12] Successfully installed flask-3.0.0
[2025-12-21 10:30:13] * Running on http://0.0.0.0:8000
[2025-12-21 10:30:45] Received webhook: {"event": "test"...}
Run Commands in a Running Service
Need to debug something? Execute commands directly:
# Check what's running
un service --execute webhooks 'ps aux'
# View recent logs
un service --execute webhooks 'tail -50 /app/server.log'
# Install a debugging tool
un service --execute webhooks 'pip install ipython'
Sleep and Wake: Save Resources
Services auto-sleep after a period of inactivity (configurable). When sleeping:
- Container is frozen (state preserved)
- No resource usage
- First request wakes it (~2 seconds)
Manual control:
# Put a service to sleep
un service --sleep webhooks
# Wake it up
un service --wake webhooks
This is perfect for development services you use intermittently.
Redeploying and Upgrading
Changed your bootstrap script? Redeploy without destroying state:
un service --redeploy webhooks --bootstrap /tmp/new-bootstrap.sh
The service restarts with the new bootstrap. For true blue-green deploys, create a new service and switch DNS.
Example: Static Site with Live Reload
Here’s a pattern for previewing a static site:
cat > /tmp/static-server.sh << 'EOF'
#!/bin/bash
pip install watchdog livereload
cat > /app/serve.py << 'PYTHON'
from livereload import Server
server = Server()
server.watch('/app/public/')
server.serve(root='/app/public', port=8000, host='0.0.0.0')
PYTHON
mkdir -p /app/public
echo "<h1>Hello from unsandbox!</h1>" > /app/public/index.html
python3 /app/serve.py
EOF
un service --name preview --ports 8000 -n semitrusted \
--bootstrap /tmp/static-server.sh
Now https://preview.svc.unsandbox.com serves your static site. Upload new files via --execute:
un service --execute preview 'cat > /app/public/about.html' < about.html
API Reference
Create Service
POST /services
{
"name": "myservice", # becomes myservice.svc.unsandbox.com
"ports": [8000], # ports to expose
"network_mode": "semitrusted", # required for outbound network
"bootstrap": "python3 app.py", # command or script content
"custom_domains": ["example.com"], # optional
"idle_timeout": 3600 # seconds before auto-sleep (optional)
}
Response:
{
"service_id": "unsb-service-abc123",
"name": "myservice",
"url": "https://myservice.svc.unsandbox.com",
"status": "starting"
}
List Services
GET /services
Response:
{
"services": [...],
"count": 3
}
Service Operations
DELETE /services/:id # Destroy service
POST /services/:id/sleep # Freeze service
POST /services/:id/wake # Unfreeze service
POST /services/:id/redeploy # Restart with new bootstrap
POST /services/:id/execute # Run command in container
GET /services/:id/logs # Get bootstrap logs
Security Model
Services run in isolated containers, just like sessions:
-
Network: Services use
semitrustedmode (outbound network allowed) - Inbound: Only specified ports are exposed, via HTTPS proxy
- Resources: CPU/memory limits per container
- Isolation: Each service in its own container, no shared state
Traffic flow:
Client → HTTPS (TLS termination) → Proxy → Container:port
All traffic is encrypted. The proxy handles SSL certificates automatically.
Pricing
Services consume compute time like sessions. A running service uses 1 slot of your concurrency limit. Sleeping services use zero. Wake-on-request means you only pay for actual usage.
CLI Quick Reference
# Create services
un service --name myapp --ports 8000 --bootstrap "python app.py"
un service --name api --ports 3000,8080 --bootstrap ./setup.sh
un service --name blog --ports 80 --domains blog.example.com -n semitrusted
# Manage services
un service --list # list all services
un service --info myapp # get details
un service --logs myapp # view bootstrap output
un service --execute myapp 'cmd' # run command in container
# Lifecycle
un service --sleep myapp # freeze (save resources)
un service --wake myapp # unfreeze
un service --redeploy myapp --bootstrap ./new-setup.sh
un service --destroy myapp # permanent deletion
What to Build
Services are perfect for:
- Webhook receivers - Debug integrations with external services
- Demo apps - Share prototypes with a real URL
- Development previews - Test before deploying to production
- API mocks - Simulate external services for testing
- Documentation sites - Host generated docs
- Bots and workers - Long-running background processes
Get Started
-
Get the CLI:
curl -L https://unsandbox.com/cli/un -o un && chmod +x un -
Set your API key:
export UNSANDBOX_API_KEY=your_key_here -
Create a service:
un service --name hello --ports 8000 -n semitrusted \ --bootstrap 'echo "Hello World" > /tmp/index.html && python3 -m http.server 8000 --directory /tmp' -
Visit your URL:
https://hello.svc.unsandbox.com
What will you deploy?
Questions? Issues? Open a ticket or reach out on Discord.