- Posted on
- • Artificial Intelligence
Artificial Intelligence Web Deployment
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence Web Deployment on Linux: From Notebook to Production
You’ve got a model that works in a notebook. Now what? The real challenge begins when you try to deliver AI to real users: reliable, fast, secure, and reproducible. This guide shows you how to deploy an AI inference API on a Linux server using Bash-friendly tooling, with clear, copy-paste commands for apt, dnf, and zypper.
What you’ll get:
A minimal, production-grade FastAPI service for inference
Systemd and Nginx setup for durability and reverse-proxying
Optional containerization with Podman or Docker
Practical steps you can adapt to your own models
Why this matters:
Speed and reliability: API + ASGI server outperforms ad-hoc scripts
Reproducibility: pinned environments and container images
Security: unprivileged service user behind a reverse proxy
Scalability: workers and statelessness make horizontal scaling possible
1) Prerequisites and Project Skeleton
Pick a clean Linux host (VM or bare-metal). We’ll install Python, Nginx, Git, and build tools. Then we’ll scaffold a small project.
Install prerequisites:
- Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y git python3 python3-pip python3-virtualenv nginx build-essential
- Fedora/RHEL/CentOS Stream (dnf):
sudo dnf install -y git python3 python3-pip python3-virtualenv nginx gcc gcc-c++ make
- openSUSE/SLE (zypper):
sudo zypper refresh
sudo zypper install -y git python3 python3-pip python3-virtualenv nginx gcc gcc-c++ make
Create a service user and directories:
sudo useradd --system --create-home --shell /usr/sbin/nologin svc-ml || true
sudo mkdir -p /opt/ai-service
sudo chown svc-ml:svc-ml /opt/ai-service
Project files:
sudo -u svc-ml bash -lc '
cd /opt/ai-service
git init .
cat > requirements.txt <<EOF
fastapi
uvicorn[standard]
transformers
torch
EOF
cat > app.py <<EOF
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
from transformers import pipeline
app = FastAPI(title="AI Inference API")
class Item(BaseModel):
text: str
class Batch(BaseModel):
texts: List[str]
# Lazy-load model on startup
@app.on_event("startup")
def load_model():
app.state.nlp = pipeline(
"sentiment-analysis",
model="distilbert-base-uncased-finetuned-sst-2-english"
)
@app.get("/healthz")
def health():
return {"status": "ok"}
@app.post("/predict")
def predict(item: Item):
out = app.state.nlp(item.text)[0]
return {"label": out["label"], "score": float(out["score"])}
@app.post("/batch_predict")
def batch_predict(batch: Batch):
out = app.state.nlp(batch.texts)
return [{"label": r["label"], "score": float(r["score"])} for r in out]
EOF
'
Create and activate a virtual environment, then install dependencies:
sudo -u svc-ml bash -lc '
cd /opt/ai-service
python3 -m virtualenv .venv
. .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
'
Quick local test:
sudo -u svc-ml bash -lc '
cd /opt/ai-service
. .venv/bin/activate
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 2
'
In another terminal:
curl -s http://127.0.0.1:8000/healthz
curl -s -X POST http://127.0.0.1:8000/predict -H "content-type: application/json" -d "{\"text\":\"I love Linux!\"}"
Tip: First run downloads the model. For faster cold-starts in production, pre-warm by calling /predict once during deploy or bake the model into a container image.
2) Service Management with systemd (Keep It Running)
Create a systemd unit so your API restarts on failure and starts at boot:
sudo tee /etc/systemd/system/ai-service.service >/dev/null <<'EOF'
[Unit]
Description=AI Inference API (FastAPI + Uvicorn)
After=network.target
[Service]
User=svc-ml
Group=svc-ml
WorkingDirectory=/opt/ai-service
Environment=HF_HOME=/opt/ai-service/.cache/huggingface
ExecStart=/opt/ai-service/.venv/bin/uvicorn app:app --host 127.0.0.1 --port 8000 --workers 2 --timeout-keep-alive 30
Restart=on-failure
RestartSec=5
# Harden a bit
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.target
EOF
sudo mkdir -p /opt/ai-service/.cache/huggingface
sudo chown -R svc-ml:svc-ml /opt/ai-service/.cache
sudo systemctl daemon-reload
sudo systemctl enable --now ai-service
sudo systemctl status ai-service --no-pager
Check:
curl -s http://127.0.0.1:8000/healthz
3) Put Nginx in Front (Security, TLS, and Performance)
Nginx acts as a reverse proxy, adds timeouts, and simplifies TLS. You installed Nginx above; ensure it’s running:
- Debian/Ubuntu (apt):
sudo systemctl enable --now nginx
- Fedora/RHEL/CentOS Stream (dnf):
sudo systemctl enable --now nginx
- openSUSE/SLE (zypper):
sudo systemctl enable --now nginx
Create a site config (replace example.com with your domain or server IP):
sudo tee /etc/nginx/conf.d/ai-service.conf >/dev/null <<'EOF'
server {
listen 80;
server_name example.com;
# Increase timeouts for model inference if needed
proxy_read_timeout 120s;
proxy_connect_timeout 5s;
proxy_send_timeout 120s;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /healthz {
proxy_pass http://127.0.0.1:8000/healthz;
}
}
EOF
sudo nginx -t
sudo systemctl reload nginx
Optional TLS:
Obtain a certificate with Let’s Encrypt (certbot or your preferred method).
Terminate TLS in Nginx and keep Uvicorn on localhost.
Firewall note:
- Debian/Ubuntu (ufw):
sudo ufw allow "Nginx Full"
sudo ufw enable
- Fedora/RHEL/CentOS (firewalld):
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
- openSUSE (firewalld):
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
4) Optional: Containerize with Podman or Docker
Containers improve portability and rollback.
Install a container engine:
Podman
- apt:
sudo apt update sudo apt install -y podman- dnf:
sudo dnf install -y podman- zypper:
sudo zypper refresh sudo zypper install -y podmanDocker (package names vary by distro)
- apt (Ubuntu/Debian):
sudo apt update sudo apt install -y docker.io sudo systemctl enable --now docker- dnf (Fedora):
# Moby (upstream Docker) in Fedora repos sudo dnf install -y moby-engine docker-compose-plugin sudo systemctl enable --now docker- zypper (openSUSE):
sudo zypper install -y docker docker-compose sudo systemctl enable --now docker
Create Dockerfile:
sudo -u svc-ml bash -lc '
cd /opt/ai-service
cat > Dockerfile <<EOF
FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
HF_HOME=/root/.cache/huggingface
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host","0.0.0.0","--port","8000","--workers","2","--timeout-keep-alive","30"]
EOF
'
Build and run with Podman:
cd /opt/ai-service
sudo podman build -t ai-svc:latest .
sudo podman run --rm -p 8000:8000 ai-svc:latest
Or with Docker:
cd /opt/ai-service
sudo docker build -t ai-svc:latest .
sudo docker run --rm -p 8000:8000 ai-svc:latest
Test:
curl -s http://127.0.0.1:8000/healthz
Tip: For faster cold starts, pre-pull models during build:
RUN python -c "from transformers import pipeline; pipeline('sentiment-analysis', model='distilbert-base-uncased-finetuned-sst-2-english')('warmup')"
5) Scale, Observe, and Optimize
Concurrency and workers:
- Start with workers = CPU cores or cores/2 and tune empirically.
- Batch requests when possible (see /batch_predict).
Caching:
- Keep HF_HOME on persistent storage to avoid re-downloading models.
- Reuse models across workers if memory allows (container memory limits apply).
Logging and metrics:
- systemd logs:
journalctl -u ai-service -f- Basic timing in app endpoints; export counters to Prometheus if needed.
Security basics:
- Run as unprivileged user (done).
- Keep API behind Nginx; lock inbound ports (only 80/443).
- Store secrets in environment files (not code).
Real-world example patterns:
CPU-only inference on small models (as shown) for cost efficiency.
GPU-backed nodes for heavy models; containerize and schedule with Kubernetes/Nomad.
Canary deploys: run new version on a second port, shift Nginx traffic gradually.
Troubleshooting Cheatsheet
venv issues: We used virtualenv to avoid distro-specific python3-venv packages. If you prefer venv and it fails, install python3-venv (apt) or your distro’s pythonX-venv package.
OOM or slow cold-starts: Use smaller models, increase instance memory, or warm the cache.
502 from Nginx: Check
journalctl -u ai-service, increase proxy_read_timeout, or add more workers.Permission errors writing model cache: Ensure
HF_HOMEdirectory is owned by your service user.
Conclusion and Next Steps
You’ve taken an AI model from “works on my laptop” to a production-grade Linux service:
FastAPI + Uvicorn inference API
Managed by systemd
Fronted by Nginx
Optionally containerized with Podman or Docker
Next step: adapt the /predict logic to your own model, add input validation and telemetry, and automate deployment with a simple Bash script or CI pipeline. When you’re ready to scale further, place this behind a load balancer and add health checks.
Want a follow-up? Ask for:
A GPU-ready Dockerfile and deployment checklist
A zero-downtime rolling deploy Bash script
Observability with Prometheus + Grafana on Linux