- Posted on
- • Artificial Intelligence
Artificial Intelligence Server Deployment
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence Server Deployment on Linux: From Zero to Inference
You’ve built an AI prototype that dazzles on your laptop—but the moment you try to put it behind an API for real users, reality sets in: inconsistent environments, missing drivers, resource contention, and a dozen “works on my machine” gotchas. This guide shows you how to deploy a reliable, reproducible AI inference server on Linux using battle-tested tools and Bash-friendly steps you can paste straight into the terminal.
We’ll cover why AI server deployment matters, walk through a practical CPU-first setup (with optional GPU acceleration), harden it with a reverse proxy and firewall, and finish with a systemd service so it all survives reboots. All installation snippets include apt, dnf, and zypper where cited.
Why this matters
Reliability beats demos: Reproducible builds and services ensure your model works the same way on every restart.
Latency and throughput: Proper serving and batching can cut costs significantly and keep users happy.
Compliance and control: On-prem or private-cloud serving means you control data and costs.
Operability: Logging, health checks, and systemd mean fewer 3 a.m. surprises.
What we’ll build (at a glance)
A dedicated Linux user and workspace for the AI server
A CPU-friendly LLM server (llama.cpp) exposing an OpenAI-compatible API
Optional GPU acceleration flags if your machine has NVIDIA or AMD GPUs
A reverse proxy (Nginx) that terminates TLS and protects your backend port
A systemd unit to auto-start and auto-recover your AI server
Firewall rules to expose only what’s needed
1) Plan your workload and serving strategy
Before you install anything, answer these:
Latency vs throughput: Low-latency chats? Consider smaller models or GPU. High-throughput batch scoring? Consider batching and parallelism settings.
CPU vs GPU: CPU is simplest and often good for small/medium models or low QPS; GPU shines for large LLMs or vision at scale.
Memory budget: Models must fit in RAM/VRAM plus overhead. Quantized GGUF models can run well on CPUs with low memory.
We’ll start CPU-first (works on almost any Linux box), then show how to flip on GPU acceleration later.
2) Prepare the host: packages, user, and firewall
Install base tools (compilers, Python, Nginx, etc.). Pick the command set for your distro.
- Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y build-essential cmake git curl wget python3 python3-pip python3-venv nginx ufw
- Fedora/RHEL/CentOS Stream (dnf):
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y cmake git curl wget python3 python3-pip nginx firewalld
- openSUSE (zypper):
sudo zypper refresh
sudo zypper install -y -t pattern devel_basis
sudo zypper install -y cmake git curl wget python3 python3-pip nginx firewalld
Optional (faster CPU math via OpenBLAS):
- apt:
sudo apt install -y libopenblas-dev
- dnf:
sudo dnf install -y openblas-devel
- zypper:
sudo zypper install -y openblas-devel
Create a dedicated user and workspace:
sudo useradd -r -m -d /opt/ai -s /bin/bash ai
sudo mkdir -p /opt/ai/models
sudo chown -R ai:ai /opt/ai
Open only the ports you need (choose one firewall family):
- UFW (Debian/Ubuntu):
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# We'll proxy the backend locally, so keep 8000 internal. If you must expose it:
# sudo ufw allow 8000/tcp
sudo ufw enable
sudo ufw status verbose
- firewalld (Fedora/openSUSE/RHEL/CentOS):
sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
# Keep backend internal; expose 8000 only if needed:
# sudo firewall-cmd --permanent --add-port=8000/tcp
sudo firewall-cmd --reload
3) Real-world example (CPU): LLM server with llama.cpp
llama.cpp is a fast, portable inference engine for LLMs. Its server binary exposes an OpenAI-compatible HTTP API, so your existing clients can usually connect with zero code changes.
Build llama.cpp:
sudo -iu ai
cd /opt/ai
git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
# Basic CPU build
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
# Optional: enable BLAS for extra CPU speed (requires OpenBLAS dev pkg, see above)
# cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS
# cmake --build build -j
Download a small, permissively available GGUF model (TinyLlama 1.1B Chat). This works without special credentials and is great for testing:
mkdir -p /opt/ai/models
cd /opt/ai/models
curl -L -o TinyLlama-1.1B-Chat.Q4_K_M.gguf \
https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/TinyLlama-1.1B-Chat-v1.0.Q4_K_M.gguf
Start the server (run in a terminal first to verify):
cd /opt/ai/llama.cpp
./build/bin/server \
-m /opt/ai/models/TinyLlama-1.1B-Chat.Q4_K_M.gguf \
--host 127.0.0.1 --port 8000 \
-c 2048 -ngl 0
-ngl 0 keeps layers on CPU (safest default).
The server exposes OpenAI-like endpoints at http://127.0.0.1:8000/v1
Test with curl:
curl -s http://127.0.0.1:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model":"TinyLlama-1.1B-Chat.Q4_K_M.gguf",
"messages":[{"role":"user","content":"In one sentence, what is Linux?"}],
"max_tokens":64
}' | jq .
You should see JSON with a generated message. If jq isn’t installed, remove the pipe.
4) Put it behind Nginx (TLS-ready and production-friendly)
Install Nginx (already installed above). Create a site config that proxies /v1 to the backend and keeps the raw Authorization header intact (important for OpenAI-compatible clients):
sudo bash -c 'cat >/etc/nginx/conf.d/ai.conf' <<'EOF'
upstream ai_backend {
server 127.0.0.1:8000;
keepalive 16;
}
server {
listen 80;
server_name _;
# Increase timeouts for long generations
proxy_read_timeout 600s;
proxy_send_timeout 600s;
location /v1/ {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Connection "";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization $http_authorization;
proxy_pass http://ai_backend;
}
# Optional simple health check
location /healthz {
return 200 "ok\n";
add_header Content-Type text/plain;
}
}
EOF
sudo nginx -t
sudo systemctl reload nginx
Optional TLS with Let’s Encrypt (ensure DNS points to this host):
- apt:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx
- dnf:
sudo dnf install -y certbot python3-certbot-nginx
sudo certbot --nginx
- zypper:
sudo zypper install -y certbot python3-certbot-nginx
sudo certbot --nginx
After this, clients can talk to your AI server through Nginx on port 443. Keep the backend on 127.0.0.1:8000 for safety.
5) Make it a service (systemd)
Create a systemd unit so the server starts at boot and auto-recovers:
sudo bash -c 'cat >/etc/systemd/system/llama-server.service' <<'EOF'
[Unit]
Description=llama.cpp AI Server
Wants=network-online.target
After=network-online.target
[Service]
User=ai
Group=ai
WorkingDirectory=/opt/ai/llama.cpp
ExecStart=/opt/ai/llama.cpp/build/bin/server \
-m /opt/ai/models/TinyLlama-1.1B-Chat.Q4_K_M.gguf \
--host 127.0.0.1 --port 8000 \
-c 2048 -ngl 0
Restart=always
RestartSec=3
# Slow model loads can take time; extend start timeout if needed
TimeoutStartSec=600
# Uncomment to constrain CPU or memory:
# MemoryMax=8G
# CPUQuota=200%
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now llama-server
sudo systemctl status llama-server --no-pager
Check logs:
journalctl -u llama-server -f
Smoke test through Nginx:
curl -s https://YOUR_DOMAIN/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"TinyLlama-1.1B-Chat.Q4_K_M.gguf","messages":[{"role":"user","content":"Say hi!"}],"max_tokens":32}'
Optional: Turn on GPU acceleration later
If your server has a supported GPU:
Install vendor drivers and runtime:
- NVIDIA: Install proprietary driver and CUDA toolkit (matching driver and libcudart). Follow NVIDIA’s official docs for your distro.
- AMD: Install ROCm per AMD’s documentation.
Rebuild llama.cpp with the correct backend:
- NVIDIA CUDA:
cd /opt/ai/llama.cpp cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON cmake --build build -j- AMD ROCm (HIPBLAS):
cd /opt/ai/llama.cpp cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_HIPBLAS=ON cmake --build build -jThen start the server with GPU layers enabled (e.g., -ngl 999 to offload as many layers as possible):
./build/bin/server -m /opt/ai/models/TinyLlama-1.1B-Chat.Q4_K_M.gguf --host 127.0.0.1 --port 8000 -c 2048 -ngl 999Adjust model size for available VRAM.
Tip: For larger deployments and multi-model serving, consider specialized servers like vLLM (OpenAI-compatible LLM serving with batching) or NVIDIA Triton (multi-framework model repo). These typically run best in containers with GPU runtime configured.
Operations checklist (quick wins)
Health checks: Nginx /healthz; also consider periodic curl checks from cron or a monitoring system.
Metrics: Node Exporter and process-level dashboards can help track CPU/RAM saturation. llama.cpp logs tokens/sec—scrape and alert.
Logging: journalctl plus Nginx access/error logs provide request-level visibility.
Rollouts: Keep binaries and models versioned (e.g., in /opt/ai/releases). Switch systemd ExecStart to roll forward/back safely.
Security: Bind backend to 127.0.0.1, restrict ports, use TLS, and consider an API key or mTLS at Nginx for private deployments.
Conclusion and next steps
You now have a reproducible, service-managed AI inference server that speaks an OpenAI-compatible API, sits safely behind Nginx, and starts on boot. From here:
Swap in a model that fits your use case (code generation, QA, RAG with embeddings).
Tune performance: enable BLAS, adjust context size and threads, or turn on GPU acceleration.
Harden: add authentication at Nginx, enable TLS auto-renew via certbot, and set resource limits in systemd.
If you want a follow-up post, ask for:
Adding RAG (Retrieval-Augmented Generation) with a vector DB
Deploying a GPU-accelerated vLLM server with batching
CI/CD for models and blue/green rollouts
Happy shipping!