How to Deploy FreeLLMAPI Using Docker Compose for Production

FreeLLMAPI can be deployed as a secure, single-container production service using Docker Compose by mounting a named volume for SQLite persistence, binding to specific host interfaces, and running healthchecks against the /api/ping endpoint.

FreeLLMAPI provides a containerized deployment solution through the tashfeenahmed/freellmapi repository. When you deploy FreeLLMAPI using Docker Compose for production workloads, the configuration leverages a multi-stage build process, non-root execution, and environment isolation to protect provider API keys and ensure service reliability.

Environment Configuration and Secrets

Before starting the container, you must prepare the environment variables that configure the encryption layer and server binding. The repository's .dockerignore explicitly excludes .env files from the build context to prevent accidental secret leakage into the image layers.

Generate a secure encryption key and create the environment file:

cd freellmapi
ENCRYPTION_KEY="$(openssl rand -hex 32)"
printf "ENCRYPTION_KEY=%s\nNODE_ENV=production\nPORT=3001\n" "$ENCRYPTION_KEY" > .env

The ENCRYPTION_KEY is critical for protecting stored provider credentials in the SQLite database. According to the source code in docker-compose.yml, the container expects these variables at runtime, not during the build phase.

Docker Compose Production Configuration

The docker-compose.yml file in the repository root defines a production service that pulls the multi-arch image ghcr.io/tashfeenahmed/freellmapi:latest or builds from the local Dockerfile. Key production settings include:

  • Image Source: Uses the GitHub Container Registry image or builds from the multi-stage Dockerfile located at ./Dockerfile
  • Runtime Environment: Explicitly sets NODE_ENV=production to disable development features
  • Port Binding: Exposes container port 3001 to the host
  • Non-root Execution: The container runs as the node user (UID 1000), with the data directory owned by that user

The compose configuration also includes an extra_hosts entry mapping host.docker.internal to the host gateway, enabling the container to reach proxy services running on the host machine without using the Docker host network.

Networking and Security Controls

By default, FreeLLMAPI binds to 127.0.0.1 (localhost only) through the HOST_BIND environment variable. This default configuration ensures the API remains single-user and unreachable from external networks, which is critical when running LLM API keys on personal infrastructure.

To expose the service to your local network (trusted environments only), override the bind address:

HOST_BIND=0.0.0.0 docker compose up -d

For localhost-only access (default secure configuration):

docker compose up -d

The Dockerfile implements security hardening by creating a dedicated node user and ensuring the application directory at /app has appropriate ownership, preventing privilege escalation vulnerabilities.

Data Persistence and Volume Management

FreeLLMAPI stores encrypted provider keys and configuration in a SQLite database located at /app/server/data. The docker-compose.yml declares a named volume freellmapi-data mapped to this path to ensure data survives container restarts and image upgrades.

Volume configuration in the compose file:

  • Volume Name: freellmapi-data
  • Container Path: /app/server/data
  • Purpose: Preserves encrypted SQLite database across container recreation

This separation of data from the container filesystem means you can update the FreeLLMAPI image with docker compose pull && docker compose up -d without losing configured provider credentials.

Healthchecks and Monitoring

Both the Dockerfile and docker-compose.yml implement a Node.js-based healthcheck that verifies the Express server is responding correctly. The healthcheck executes:

node -e "fetch('http://127.0.0.1:3001/api/ping').then(r=>r.ok||process.exit(1)).catch(()=>process.exit(1))"

Docker marks the container as unhealthy if this endpoint fails, enabling orchestration systems to restart the service automatically.

To monitor logs and verify deployment status:

docker compose logs -f freellmapi

Step-by-Step Production Deployment

Complete the following steps to deploy FreeLLMAPI using Docker Compose for production:

  1. Clone the repository and navigate to the project directory:
git clone https://github.com/tashfeenahmed/freellmapi.git
cd freellmapi
  1. Create the environment file with encryption key:
ENCRYPTION_KEY="$(openssl rand -hex 32)"
printf "ENCRYPTION_KEY=%s\nPORT=3001\n" "$ENCRYPTION_KEY" > .env
  1. Start the service in detached mode:
docker compose up -d
  1. Verify the healthcheck manually (optional diagnostic):
docker compose exec freellmapi node -e "fetch('http://127.0.0.1:3001/api/ping').then(r=>console.log('Status:', r.status)).catch(e=>console.error('Health check failed'))"
  1. Expose to LAN (if needed for network access):
docker compose down
HOST_BIND=0.0.0.0 docker compose up -d

Summary

Deploying FreeLLMAPI in production using Docker Compose provides a reproducible, isolated environment with the following characteristics:

  • Secure by default: Runs as non-root node user with localhost-only binding (127.0.0.1)
  • Persistent storage: Uses named volume freellmapi-data mounted at /app/server/data for SQLite encryption keys
  • Production hardened: Multi-stage build excludes development dependencies, .dockerignore prevents secret leakage
  • Health monitored: Built-in healthcheck polls /api/ping to verify service availability
  • Network flexible: Supports host.docker.internal for proxy access and configurable HOST_BIND for LAN exposure

Frequently Asked Questions

How do I backup the FreeLLMAPI SQLite database?

The SQLite database resides in the Docker volume mounted at /app/server/data. To backup, use docker compose cp to copy the file from the running container: docker compose cp freellmapi:/app/server/data ./backup-$(date +%Y%m%d). Alternatively, backup the named volume freellmapi-data directly using standard Docker volume backup procedures.

Can I use a pre-built image instead of building locally?

Yes. The docker-compose.yml references ghcr.io/tashfeenahmed/freellmapi:latest by default. You can pull this image directly without cloning the repository, though you still need the docker-compose.yml file and an .env file with your ENCRYPTION_KEY to run the container.

Why does the container default to localhost-only binding?

The HOST_BIND environment variable defaults to 127.0.0.1 in the application configuration to prevent accidental exposure of API endpoints to the public internet. This security measure ensures that without explicitly setting HOST_BIND=0.0.0.0, the service remains accessible only from the host machine, protecting your LLM provider API keys from network-based attacks.

How do I update FreeLLMAPI to a newer version?

Pull the latest image and recreate the container while preserving your data volume: docker compose pull && docker compose up -d. The named volume freellmapi-data persists your encrypted provider configuration, so the new container instance retains all settings after the update.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →