DockerSelf-HostingAIAI Coding Agents

New API with Docker: a self-hosted LLM gateway with keys, quotas and many providers (Linux, Windows, Mac)

Before you start

  • 21 min read

Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#

New API is a free, self-hosted AI gateway: you add your model providers once (Ollama, OpenAI, Anthropic, Gemini and more), then every app, person or agent calls one address with its own key, quota and usage log.

New API official logo

Logo: the official New API project (github.com/QuantumNous/new-api)

The project calls itself "a self-hosted AI gateway for applications, agents, and teams". It suits a family or small team sharing model access, or a home lab that wants per-app keys and a usage dashboard. It is a gateway, not a model: Ollama or a cloud account must sit behind it.

WhatValue (official docs and releases, read November 2026)
Current versionv1.0.0-rc.48, a release candidate published in November 2026. GitHub marks it "Latest"; no final 1.0.0 exists yet
Image to pincalciumion/new-api:v1.0.0-rc.48 (tag checked on Docker Hub, amd64 and arm64)
Time neededAbout 25 minutes with Ollama running (our estimate)
Size and RAMImage about 78 MB compressed (Docker Hub). No RAM figure in the docs
PortsTCP 3000 (web console and API)
LicenceAGPL-3.0 plus attribution terms (LICENSE at the tag)
Official docsdocs.newapi.ai and the repository

Screenshot of the New API dashboard with usage statistics, a quota chart and the console menu

Image: the official New API project (README, Screenshots). The README says the data shown is simulated.

At a glance:

  • What it is: one gateway in front of many providers, speaking OpenAI, Anthropic and Gemini request formats.
  • What you control: users, groups, API keys with quota and expiry, channel priority, prices, usage logs.
  • Project status: alive and busy. It moved from the Calcium-Ion to the QuantumNous organisation on GitHub and is built on One API.
  • The catch: every version since April 2026 is a release candidate (48 so far). Pin one and back up before each update.
  • Platforms: the docs recommend Linux (amd64, arm64). Windows and Mac work through Docker Desktop in our commands, untested.
  • No default password: a setup wizard creates the admin account on first visit.

How it fits together#

Apps send one kind of request with a New API key. New API checks the key, group and quota, picks a channel, and forwards the call to Ollama on your machine or to a cloud provider. The admin works in the same web console.

Two-lane diagram: your apps send a base URL and key through an optional Caddy or Traefik HTTPS front door to New API on port 3000, which checks key, group and quota and calls Ollama on your machine or a cloud provider; in the second lane you open the web console through the same door while New API stores data in PostgreSQL, Redis and the data and logs folders

Drawn for this guide from the official compose file and docs. Dashed parts are optional.

Before you start#

You need Docker with Compose and a model source.

SystemWhat to have
LinuxDocker Engine with the Compose plugin, curl, openssl (amd64 or arm64)
WindowsDocker Desktop and PowerShell 7 (the secret generator needs .NET 6 or newer). Not named in the docs
MacDocker Desktop, Terminal, curl, openssl. Not named in the docs

Check the tools:

Run in terminalbash
docker --version
docker compose version

On Windows, also check pwsh --version.

Checklist:

  • [ ] Ollama runs with at least one model (ollama pull llama3.1); see our Ollama guide
  • [ ] Port 3000 is free on this machine
  • [ ] Any older New API or One API data is backed up
  • [ ] For the HTTPS section only: a DNS name for the server and ports 80 and 443 free

Tested by DIY Lab Hub: not yet. Commands come from the official compose file, README and docs read in November 2026; we did not run them.

Step 1: Create the folders and the secrets#

New API needs three secrets: the PostgreSQL password, the Redis password and SESSION_SECRET. The official compose file ships with password 123456, and the README asks for a persistent random SESSION_SECRET. We keep all three in .env.

Linux#

Run in terminalbash
mkdir -p ~/docker_volumes/new-api/{data,logs,backups}
cd ~/docker_volumes/new-api
umask 077
cat > .env << EOF
POSTGRES_PASSWORD=$(openssl rand -hex 16)
REDIS_PASSWORD=$(openssl rand -hex 16)
SESSION_SECRET=$(openssl rand -hex 32)
TZ=UTC
EOF
chmod 600 .env

Windows (PowerShell)#

Codepowershell
New-Item -ItemType Directory -Force "$HOME\docker_volumes\new-api\data","$HOME\docker_volumes\new-api\logs","$HOME\docker_volumes\new-api\backups"
Set-Location "$HOME\docker_volumes\new-api"
function New-Hex($n) { [Convert]::ToHexString([Security.Cryptography.RandomNumberGenerator]::GetBytes($n)).ToLower() }
@"
POSTGRES_PASSWORD=$(New-Hex 16)
REDIS_PASSWORD=$(New-Hex 16)
SESSION_SECRET=$(New-Hex 32)
TZ=UTC
"@ | Set-Content -Path .env -Encoding utf8

Mac (Terminal)#

Same commands as Linux.

Hex strings are safe inside the database address; symbols such as @ would break it. Set TZ to your own zone if you like (the official file uses Asia/Shanghai).

Check it worked. Linux and Mac: ls -l .env shows -rw------- and grep -c = .env prints 4. Windows: (Get-Content .env).Count prints 4. Never paste the file's content anywhere.

Tip: Copying .env.example alone does nothing: the README says only Compose's environment or env_file injects variables into the container.

Step 2: Write the Compose file and start New API#

This is the official compose file with changes: pinned image, secrets from .env, no obsolete version: line, restart: unless-stopped, and port 3000 published on 127.0.0.1 only (the official file publishes it everywhere). Redis is pinned to 7.4 (our choice; the official file says latest). extra_hosts lets the container reach Ollama on the host.

Linux#

Run in terminalbash
cd ~/docker_volumes/new-api
cat > docker-compose.yml << 'EOF'
services:
  new-api:
    image: calciumion/new-api:v1.0.0-rc.48
    container_name: new-api
    restart: unless-stopped
    command: --log-dir /app/logs
    ports:
      - "127.0.0.1:3000:3000"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./data:/data
      - ./logs:/app/logs
    environment:
      - SQL_DSN=postgresql://root:${POSTGRES_PASSWORD}@postgres:5432/new-api
      - REDIS_CONN_STRING=redis://:${REDIS_PASSWORD}@redis:6379
      - SESSION_SECRET=${SESSION_SECRET}
      - TZ=${TZ}
      - ERROR_LOG_ENABLED=true
      - BATCH_UPDATE_ENABLED=true
      - NODE_NAME=new-api-node-1
    depends_on:
      - redis
      - postgres
    networks:
      - new-api-network
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O - http://localhost:3000/api/status | grep -o '\"success\":\\s*true' || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3

  redis:
    image: redis:7.4
    container_name: new-api-redis
    restart: unless-stopped
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]
    networks:
      - new-api-network

  postgres:
    image: postgres:15
    container_name: new-api-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: new-api
    volumes:
      - pg_data:/var/lib/postgresql/data
    networks:
      - new-api-network

volumes:
  pg_data:

networks:
  new-api-network:
    driver: bridge
EOF
docker compose config --quiet && echo "compose file OK"
docker compose up -d
docker compose ps
docker compose logs --tail=50 new-api

Windows (PowerShell)#

Save the same YAML as docker-compose.yml in $HOME\docker_volumes\new-api (open it with notepad docker-compose.yml, paste the YAML from the Linux block, save as UTF-8), then:

Codepowershell
Set-Location "$HOME\docker_volumes\new-api"
docker compose config --quiet; if ($?) { "compose file OK" }
docker compose up -d
docker compose ps
docker compose logs --tail=50 new-api

Mac (Terminal)#

Same commands as Linux.

PostgreSQL stays on a named volume, as in the official file; we back it up with pg_dump.

Check it worked. docker compose ps shows new-api running and, after about a minute, healthy. The health check calls /api/status; from the host:

Run in terminalbash
curl -s http://localhost:3000/api/status

On Windows use curl.exe. The docs publish no sample output; the health check passes when the JSON contains "success":true.

Tip: Copy the image tag exactly. latest follows every published build, and every build is a release candidate.

Step 3: Create the admin account in the setup wizard#

There is no default login. The docs say the first visit "will automatically redirect to the initialization page" where you set the administrator account. The wizard also offers Self-use mode, which the FAQ names as the fix for "Ratio or price not configured": tick it for a private instance. Leave the demo-site option off.

Linux#

Open http://localhost:3000 on the server, or from another computer through a tunnel left running:

Run in terminalbash
ssh -N -L 3000:127.0.0.1:3000 <your-user>@<your-server-address>

Windows (PowerShell)#

Open http://localhost:3000. For another machine, run the same tunnel and keep the window open:

Run in terminalpowershell
ssh -N -L 3000:127.0.0.1:3000 <your-user>@<your-server-address>

Mac (Terminal)#

Open http://localhost:3000; for another machine use the Linux tunnel command.

The setup code limits the username to 12 characters; the two password fields must match (release notes: 8 to 128 characters).

Check it worked. The login works and the left menu shows Dashboard, API Keys, Channels, Users and System Settings.

Tip: Save the admin password in a password manager now. Old tutorials say root and 123456; the current docs describe only the wizard.

Step 4: Add a channel for Ollama#

A channel is one provider connection ("one provider's API key", say the docs). Open Channels and choose Add Channel.

Linux#

The web console is the same in a browser on every system.

Windows (PowerShell)#

Same in the browser.

Mac (Terminal)#

Same in the browser.

Fill in the form:

FieldWhat to enter
TypeOllama
Namelocal-ollama
KeyAny text, such as ollama. The form needs a non-empty key; Ollama ignores it
ModelsThe model you pulled, for example llama3.1 (or "Fill Default Models")
Base URLhttp://host.docker.internal:11434 (no /v1, no path)
GroupLeave the default group

The adaptor source at the release tag adds /api/chat to the base URL, so the base URL has no path. A per-channel switch for OpenAI-compatible chat uses /v1/chat/completions instead.

For Ollama on another machine, use its address. On Linux, Ollama listens on 127.0.0.1 by default, so a container may not reach it; our LiteLLM guide explains the OLLAMA_HOST fix in its Step 3. Docker Desktop resolves host.docker.internal on Windows and Mac.

Press Test on the channel row; the docs say a dialog shows the response time and the result.

Check it worked. The test shows a response time and the channel stays green (active).

Step 5: Create an API key for an app#

Never give an app your admin login. Open API Keys and choose Create API Key.

Linux#

Browser only, as in Step 4.

Windows (PowerShell)#

Browser only.

Mac (Terminal)#

Browser only.

Settings from the docs:

SettingUse
NameThe app or person, for example laptop-test
Quota or Unlimited QuotaToken quota is separate from the account quota; it only caps this key
Expiration timeThe key is refused after this moment
Model restrictionsLimit the key to llama3.1; blank means no limit
IP whitelistOptional, one IP or CIDR per line

Save, then click the masked key to copy it (it starts with sk- in the docs' examples). The docs call keys "equivalent to passwords": keep them out of chats, repositories and screenshots, and delete a leaked key at once.

Check it worked. The key appears in the list as enabled.

Tip: Make one key per app. When one app misbehaves you disable that key and the others keep working.

Step 6: Send your first request#

Use the New API key, never the admin password. The address for OpenAI-style clients is http://localhost:3000/v1.

Linux#

Run in terminalbash
export NEW_API_KEY='<YOUR_NEW_API_KEY>'
curl --fail-with-body http://localhost:3000/v1/models -H "Authorization: Bearer ${NEW_API_KEY}"
curl --fail-with-body http://localhost:3000/v1/chat/completions \
  -H "Authorization: Bearer ${NEW_API_KEY}" -H "Content-Type: application/json" \
  -d '{"model":"llama3.1","messages":[{"role":"user","content":"Say hello in five words."}]}'

Windows (PowerShell)#

Codepowershell
$h = @{ Authorization = "Bearer <YOUR_NEW_API_KEY>" }
Invoke-RestMethod -Uri http://localhost:3000/v1/models -Headers $h
$body = @{ model = "llama3.1"; messages = @(@{ role = "user"; content = "Say hello in five words." }) } | ConvertTo-Json -Depth 5
Invoke-RestMethod -Uri http://localhost:3000/v1/chat/completions -Method Post -Headers $h -ContentType "application/json" -Body $body

Mac (Terminal)#

Same commands as Linux.

Check it worked. /v1/models lists only the models this key may use. The chat call returns OpenAI-style JSON with the answer in choices[0].message.content (the docs show no sample output). Usage Logs in the console now lists the call with channel, tokens and cost.

Screenshot of the New API usage log table with columns for time, channel, user, token, model, tokens, cost and timing

Image: the official New API project (README, Screenshots). Simulated data, as the README states.

Any app with an "OpenAI base URL" and "API key" setting works the same way. The docs also cover desktop clients and coding tools such as Claude Code and the Codex CLI under AI Applications.

Quotas, groups and routing in plain words#

The FAQ gives the price formula: Quota = Group Ratio x Model Ratio x (prompt tokens + completion tokens x completion ratio).

  • Groups decide which channels a user or key may use; user, key and channel each carry a group.
  • Priority: a higher number is used first. Weight splits requests between channels of the same priority (the FAQ: weights 2:1 give a 2:1 split).
  • Failover idea: Ollama at priority 2 and a cloud channel at priority 1 means cloud is used only when the local channel fails. We did not test this.
  • Cloud keys are your own accounts. The project's notice says to use only keys you are authorised to use and follow each provider's terms.

Put it behind HTTPS (with or without Traefik)#

For a server people reach by name, put New API behind HTTPS and drop the host port. Local-only users can keep 127.0.0.1:3000 and skip this section. The README asks for HTTPS in front of the console, with streaming and WebSocket upgrades passed through. Both routes need a DNS record for the server.

First edit the new-api service (both routes): delete the ports: lines, join the external proxy network, and set the two cookie variables to your exact HTTPS address (no path, no wildcard):

File contentyaml
    environment:
      # keep the existing lines, and add these two
      - SESSION_COOKIE_SECURE=true
      - SESSION_COOKIE_TRUSTED_URL=https://new-api.<your-domain>
    networks:
      - new-api-network
      - proxy

At the bottom of the file, add the network next to new-api-network, and create it once with docker network create proxy:

File contentyaml
networks:
  new-api-network:
    driver: bridge
  proxy:
    external: true

With Traefik#

On a server that already runs Traefik v3 with the Docker provider, add these labels to the new-api service. We assume an entrypoint called https; use your own name.

File contentyaml
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"
      - "traefik.http.routers.new-api.rule=Host(`new-api.<your-domain>`)"
      - "traefik.http.routers.new-api.entrypoints=https"
      - "traefik.http.routers.new-api.tls=true"
      - "traefik.http.services.new-api.loadbalancer.server.port=3000"

Run docker compose up -d in the New API folder. Check it worked: curl -I https://new-api.<your-domain>/ returns a status line over HTTPS.

Without Traefik: Caddy#

Choose this if you have no Traefik. Caddy gets and renews its own certificates: Let's Encrypt for a public domain, tls internal for a local certificate at home. Its reverse_proxy passes WebSocket upgrades and flushes text/event-stream responses at once, so streamed answers need no extra settings. Caddy's Docker docs advise mounting the folder, not one Caddyfile, so we mount conf.

Run in terminalbash
mkdir -p ~/docker_volumes/caddy/{conf,data,config}
cd ~/docker_volumes/caddy

On Windows: New-Item -ItemType Directory -Force "$HOME\docker_volumes\caddy\conf","$HOME\docker_volumes\caddy\data","$HOME\docker_volumes\caddy\config". Save as docker-compose.yml there (caddy:2.11.8 was the latest release in November 2026):

File contentyaml
services:
  caddy:
    image: caddy:2.11.8
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./conf:/etc/caddy
      - ./data:/data
      - ./config:/config
    networks:
      - proxy

networks:
  proxy:
    external: true

Save as conf/Caddyfile for a public domain:

File contenttext
new-api.example.com {
    reverse_proxy new-api:3000
}

For a home-only name, add tls internal:

File contenttext
new-api.home.arpa {
    tls internal
    reverse_proxy new-api:3000
}

Run docker compose up -d in both folders. With tls internal, each device must trust Caddy's root certificate; our Caddy guide shows the steps for Linux, Windows and Mac in its Step 5.

Check it worked. curl -I https://new-api.example.com/ (Windows: curl.exe) returns a status line over HTTPS. A home name shows a padlock only after the root is trusted.

Tip: A console that loops back to the login page usually has a SESSION_COOKIE_TRUSTED_URL that differs from the browser's address by one character (scheme, name or port). Copy it from the address bar.

Security and testing#

A gateway holds your provider keys and spends your money, so treat the console like a bank page.

ControlHow
Admin accountLong unique password. The README lists two-factor authentication and passkeys; see the clock warning in Troubleshooting before enabling them
Port 3000127.0.0.1 or no host port behind HTTPS. Never forward it on your router
SecretsOnly in .env, mode 600, never in git or issue reports
SESSION_SECRETRandom and stable; all nodes of one deployment share it
RegistrationIn System Settings, check the "Open Registration" switch and turn it off for a private gateway
App keysOne per app, with a model list, an expiry and, if you can, an IP list
TRUSTED_PROXIESUnset trusts loopback and private ranges (and warns). Set your proxy's network, or none
Private addressesAn issue (closed, October 2026) says the SSRF protection can only allow private IPs globally, which also covers user-sent image and file URLs. Keep it off unless needed
TelemetryThe docs describe none; Google Analytics and Umami variables in the compose file are off unless you set them

Quick tests after each change (Windows: Set-Location "$HOME\docker_volumes\new-api" and curl.exe):

Run in terminalbash
cd ~/docker_volumes/new-api
docker compose ps
docker compose logs --tail=100 new-api
curl -s http://localhost:3000/api/status

Release candidates: what that means for you#

The last 0.x image, v0.13.2, is from late April 2026; v1.0.0-rc.1 followed two days later and rc.48 came in November 2026. No final 1.0.0 exists, so the newest "stable" is a candidate. From the notes:

  • rc.38 called the experimental plugin system "still not recommended for production use". The later notes we read do not repeat it.
  • rc.46 fixes a security problem ("please upgrade soon"), so do not stay on an old candidate forever.
  • Updates change behaviour: rc.41 replaced the dashboard access token with named tokens, rc.44 cleared Playground history once, rc.48 signs the Redis caches (upgrade all nodes together).

Our rule: pin a tag, back up the database, read the notes, update when something you need is fixed, and note the old tag. The docs show rollback by pulling an older tag but warn that database changes may not be compatible, so the backup is your real way back.

New API or LiteLLM: which should you choose?#

Both give one OpenAI-style address with keys and budgets. See our LiteLLM guide. The table lists only what we read in each project's docs.

QuestionNew API (rc.48)LiteLLM (our guide, v1.106.3)
Adding modelsWeb console channels, stored in the databaseconfig.yaml file, plus an Admin UI with Postgres
PeopleUsers, groups, wallets, subscriptions, redemption codesVirtual keys per app or person
Cost controlQuota units from group and model ratiosMoney budgets per key, with time windows
Release stateRelease candidates onlyNumbered releases
LanguageEnglish docs; many issues and notes also in ChineseEnglish
LicenceAGPL-3.0 with attribution termsSee its repository

Choose New API when people should sign in and see their own quota and usage in a ready console. Choose LiteLLM when you want everything in a config file you keep in git, or no release candidates. Run only one on a port.

Common mistakes#

From the official docs' warnings, real GitHub issues and common AI assistant answers.

MistakeWhy it happensDo this instead
Pulling latestThe README: latest "can change". Issue 7361 (closed, September 2026): after a latest pull, memory went from about 75 MiB to 1.77 GB and a 2 GB host ran outPin v1.0.0-rc.48; change it yourself after reading the notes
Hopping between tagsIssue 4178 (closed, April 2026): latest to nightly gave permission denied for schema public (SQLSTATE 42501)Stay on one tag; dump the database before any switch
Keeping the official example passwords and portThe compose file uses 123456 and publishes 3000:3000 on all interfacesUse the .env secrets and 127.0.0.1:3000
Server clock a few minutes offIssue 7735 (open): changing a password, adding 2FA or creating a key failed with "server returned no verification credential"; the proof token lives about 60 seconds and the clock was 2 to 9 minutes offEnable time sync on the host first
Too many login sessionsIssue 6972 (open): admin login refused with "active login session count reached the limit"Raise USER_SESSION_ACTIVE_LIMIT (the issue used 100), restart, sign out other sessions
Token quota versus account quota, or no model priceFAQ: token quota only caps one key; a model without a price gives "Ratio or price not configured"Check the key's quota (or Unlimited Quota); set prices or turn on Self-use mode
localhost or /v1 in the Ollama base URLlocalhost is the container itself; the adaptor adds /api/chat itselfhttp://host.docker.internal:11434, no path
AI assistants: "the admin login is root / 123456"Old One API tutorials; the current docs use a setup wizardCreate the admin in the wizard
AI assistants: inventing OPENAI_API_KEY variables or a config.yaml for modelsMixing up LiteLLM; New API keeps provider keys in channelsAdd providers under Channels; use only variables from the official environment page

Tip: Before pasting a compose file from a chat answer, compare the image tag and the variable names with the official file at the release tag you pin.

Tip: When an upstream error appears, repeat the same request against the provider directly. The maintainers' issue template asks for that comparison before a report.

Tip: Reloading the console many times in a row can lock the admin out for a short while (issue 7783, open). Wait a minute instead of clicking again.

Troubleshooting#

ProblemSolution
Container restartsdocker compose logs --tail=100 new-api; check .env has four lines and docker compose config shows no empty password
Channel test: connection refusedOllama is not reachable from the container: check the Base URL and OLLAMA_HOST (LiteLLM guide, Step 3)
invalid character '<' looking for beginning of valueThe reply was a web page; the FAQ says a deployment IP or proxy blocked by Cloudflare is the usual cause
Ratio or price not configured, please contact the administrator to set it.Set ratios in System Settings or enable Self-use mode
"No available channels"Check user group, channel group and the channel's model list
Current group load is saturated, please try again later.An upstream channel returned 429; add a channel or wait
Database consistency has been corrupted, please contact the administrator?Invalid records after hand-editing the database; use the console, not SQL
Memory keeps growingdocker stats new-api; maintainers ask for a pprof profile (ENABLE_PPROF in .env.example); roll back to a tag you trusted

Known bugs (open, November 2026)#

  • Issue 6972: the active-session limit can block admin login (workaround above; a fix pull request is open).
  • Issue 7735: sensitive actions fail when the server clock is off. Fix the clock.
  • Issue 7783: console reloads share a rate-limit bucket with login; a pull request is open.

Updates and backups#

Update. Read the release notes, back up, change the tag in docker-compose.yml, then run the docs' order (Windows: use $HOME\docker_volumes\new-api):

Run in terminalbash
cd ~/docker_volumes/new-api
docker compose pull
docker compose down
docker compose up -d
docker compose logs --tail=100 new-api

Then sign in, test a channel and make one call. The docs allow automatic updaters such as Watchtower only for test setups.

Back up. Save as backup.sh, then chmod 700 backup.sh. It dumps PostgreSQL and archives the folders; the archive holds .env, so keep it private and copy it to another machine:

File contentbash
#!/usr/bin/env bash
set -euo pipefail
cd ~/docker_volumes/new-api
stamp=$(date +%F)
docker compose exec -T postgres sh -c 'pg_dump -U root new-api > /tmp/new-api.sql'
docker compose cp postgres:/tmp/new-api.sql "backups/new-api-$stamp.sql"
tar -czf "backups/new-api-files-$stamp.tar.gz" data .env docker-compose.yml
chmod 600 backups/new-api-*

Linux#

Schedule at 03:00 with crontab -e:

File contenttext
0 3 * * * /home/<your-user>/docker_volumes/new-api/backup.sh

Windows (PowerShell)#

Save as backup.ps1 and schedule it in Task Scheduler (daily 03:00, program pwsh, arguments -File "<full path to backup.ps1>"):

Codepowershell
Set-Location "$HOME\docker_volumes\new-api"
$stamp = Get-Date -Format yyyy-MM-dd
docker compose exec -T postgres sh -c "pg_dump -U root new-api > /tmp/new-api.sql"
docker compose cp postgres:/tmp/new-api.sql "backups\new-api-$stamp.sql"
Compress-Archive -Path data, .env, docker-compose.yml -DestinationPath "backups\new-api-files-$stamp.zip" -Force

Mac (Terminal)#

Same script and crontab line as Linux, with your home under /Users/<your-user>.

Restore test. Restore into a throwaway database, never over the live one (Windows: same lines in PowerShell):

Run in terminalbash
cd ~/docker_volumes/new-api
docker compose cp backups/new-api-<date>.sql postgres:/tmp/restore.sql
docker compose exec -T postgres createdb -U root restore_test
docker compose exec -T postgres psql -U root -d restore_test -f /tmp/restore.sql -q
docker compose exec -T postgres psql -U root -d restore_test -c '\dt'
docker compose exec -T postgres dropdb -U root restore_test

The \dt listing should show the New API tables.

Performance and resources#

The docs give no memory, CPU or disk figures, so we give none for rc.48. One reporter measured about 75 MiB resident memory on rc.36; it is the only number we found. Measure your own:

  • Live use: docker stats new-api new-api-postgres new-api-redis.
  • Timeouts: STREAMING_TIMEOUT (compose comment: default 120 seconds; raise it for empty completions) and RELAY_TIMEOUT (default 0, no limit).
  • Caches: BATCH_UPDATE_ENABLED=true and Redis are on in the official file.
  • Several instances: the docs describe a cluster mode with a shared database and SESSION_SECRET; update the primary node first. Not covered here.
  • In the console: the Dashboard shows usage and success rates; the usage log shows time to first token per call.

FAQ#

Is New API free? Yes, under AGPL-3.0. You still pay the providers behind your channels. The README gives a contact address for other licence terms.

Does it need a GPU? No, it only forwards requests. A GPU matters for Ollama or vLLM behind it.

Can I resell model access? The README says it is for lawful, authorised use and tells public-service operators to meet filing, licensing and upstream obligations. Read it first.

Is the project abandoned or renamed? Neither. It is active and sits under the QuantumNous organisation; the old Calcium-Ion address redirects. The Docker Hub name is still calciumion/new-api.

Sources#

Checked against the official docs on 2026-11-05.