AI Agents
Open Source
Deploy SmolAgents on a RamNode VPS
Hugging Face's minimalist code-first agent framework, behind a FastAPI wrapper with Docker-sandboxed code execution and TLS-terminated Nginx.
At a Glance
| Project | SmolAgents 1.24+ |
| License | Apache 2.0 |
| Recommended Plan | RamNode Premium NVMe 4 vCPU / 8 GB |
| OS | Ubuntu 24.04 LTS |
| Estimated Setup Time | 45 minutes |
1
Initial Server Hardening
Create non-root user + base packages
adduser --disabled-password --gecos "" agent
usermod -aG sudo agent
rsync --archive --chown=agent:agent ~/.ssh /home/agent
sudo apt update && sudo apt -y upgrade
sudo apt -y install build-essential ca-certificates curl gnupg lsb-release \
git ufw fail2ban unattended-upgrades \
python3.12 python3.12-venv python3-pip python3-devSSH hardening
# /etc/ssh/sshd_config.d/99-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
AuthenticationMethods publickey
AllowUsers agentUFW
sudo systemctl reload ssh
sudo ufw default deny incoming && sudo ufw default allow outgoing
sudo ufw allow 22/tcp && sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
sudo ufw enable2
Install Docker (Sandbox Executor)
Add official repo + install
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker agent/etc/docker/daemon.json (sandbox safety net)
{
"log-driver": "json-file",
"log-opts": {"max-size": "10m", "max-file": "3"},
"default-ulimits": {"nofile": {"Name": "nofile", "Hard": 4096, "Soft": 4096}},
"no-new-privileges": true,
"icc": false,
"userland-proxy": false
}Restart
sudo systemctl restart docker
docker run --rm hello-world3
Python Environment + SmolAgents
Project + venv
sudo mkdir -p /opt/smolagents && sudo chown agent:agent /opt/smolagents
cd /opt/smolagents
python3.12 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip wheel
pip install "smolagents[toolkit,litellm,docker,mcp]" fastapi uvicorn python-dotenv
pip freeze > requirements.txt/opt/smolagents/.env
HF_TOKEN=hf_xxx
OPENAI_API_KEY=sk-xxx
ANTHROPIC_API_KEY=sk-ant-xxxLock the file
chmod 600 /opt/smolagents/.env4
Minimal Agent Service
/opt/smolagents/app.py
import os
from contextlib import asynccontextmanager
from typing import Optional
from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from smolagents import CodeAgent, WebSearchTool, LiteLLMModel
load_dotenv("/opt/smolagents/.env")
MODEL_ID = os.environ.get("SMOLAGENTS_MODEL_ID", "anthropic/claude-sonnet-4-5")
MAX_STEPS = int(os.environ.get("SMOLAGENTS_MAX_STEPS", "8"))
EXECUTOR = os.environ.get("SMOLAGENTS_EXECUTOR", "docker")
class RunRequest(BaseModel):
task: str = Field(..., min_length=1, max_length=4000)
max_steps: Optional[int] = Field(default=None, ge=1, le=20)
class RunResponse(BaseModel):
result: str; steps_used: int
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.model = LiteLLMModel(model_id=MODEL_ID)
yield
app = FastAPI(lifespan=lifespan, title="SmolAgents Service")
@app.get("/health")
def health(): return {"status": "ok", "model": MODEL_ID, "executor": EXECUTOR}
@app.post("/run", response_model=RunResponse)
def run(req: RunRequest):
try:
with CodeAgent(tools=[WebSearchTool()], model=app.state.model,
executor_type=EXECUTOR, max_steps=req.max_steps or MAX_STEPS) as agent:
result = agent.run(req.task)
return RunResponse(result=str(result), steps_used=len(agent.memory.steps))
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc))5
Run under systemd
/etc/systemd/system/smolagents.service
[Unit]
Description=SmolAgents FastAPI service
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service
[Service]
Type=simple
User=agent
Group=agent
WorkingDirectory=/opt/smolagents
EnvironmentFile=/opt/smolagents/.env
ExecStart=/opt/smolagents/.venv/bin/uvicorn app:app \
--host 127.0.0.1 --port 8000 --workers 2 \
--proxy-headers --forwarded-allow-ips=127.0.0.1
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/opt/smolagents
ProtectKernelTunables=true
[Install]
WantedBy=multi-user.targetEnable
sudo systemctl daemon-reload
sudo systemctl enable --now smolagents
journalctl -u smolagents -f6
Nginx Reverse Proxy + TLS
Install nginx + certbot
sudo apt -y install nginx certbot python3-certbot-nginx/etc/nginx/sites-available/smolagents.conf
server {
listen 80;
server_name agents.example.com;
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
server_name agents.example.com;
ssl_certificate /etc/letsencrypt/live/agents.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/agents.example.com/privkey.pem;
client_max_body_size 1m;
proxy_read_timeout 300s;
if ($http_x_agent_key != "REPLACE_WITH_LONG_RANDOM_STRING") { return 403; }
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Enable + cert
sudo ln -s /etc/nginx/sites-available/smolagents.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d agents.example.com --redirect7
Hardening Checklist
- Confirm uvicorn runs as
agent, not root - Confirm
ss -tlnpshows 8000 bound to 127.0.0.1 only - .env is mode 600, owned by
agent - Set sane
max_stepsceiling per request - Mount tmpfs into the Docker sandbox, never a host path
- Audit every tool — each is part of the agent's attack surface
