GPT-Load 1.4.12 on AWS User Guide
Overview
This guide covers launching and verifying GPT-Load 1.4.12 on Ubuntu 24.04 from cloudimg on Amazon EC2. It is one version of the cloudimg Hardened Ollama, LiteLLM & Self Hosted LLM Server AMIs listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. The other LLM servers, gateways and chat interfaces in the listing are described on the listing's guide hub.
GPT-Load is an open-source, high-performance LLM API key pool manager. Its unit of work is a group: one upstream provider (OpenAI, Google Gemini, Anthropic or any OpenAI-compatible endpoint) plus a pool of many API keys for it. Requests are relayed transparently to the provider's own native API, while GPT-Load rotates through the pool, health-checks every key, takes failing keys out of rotation and restores them when they recover. Your application code keeps using its normal SDK; only the base URL and API key change.
GPT-Load is a relay, not a model host: it needs no GPU and runs on a small CPU instance. It is a single Go binary with its web dashboard compiled in, with an embedded SQLite store and an in-process cache, which is why this image needs no container runtime, no database server and no cache server.
What is on the image:
- GPT-Load 1.4.12, compiled by cloudimg from the upstream source at tag
v1.4.12(commit18e8b7893d6b5da0ba43178d21fccba82a4674c0) with Go 1.26.9 and patched Go dependencies, run bygpt-load.serviceas the unprivilegedgpt-loaduser - GPT-Load bound to loopback only (
127.0.0.1:3001), with nginx as the only network-facing service - HTTPS on port 443 with a self-signed certificate created on your instance's first boot; port 80 redirects to HTTPS
- A per-instance gate password, auth key and encryption key, generated on first boot into a root-only file
- An embedded SQLite store in
/var/lib/gpt-load/data(mode 0700) with no group and no provider key configured: you add your own keys, which are encrypted at rest gpt-load-set-hostname, a helper that serves GPT-Load under your own DNS name and re-issues the certificate for it- The build provenance (toolchain, the exact dependency changes, the vulnerability scan) and a licence inventory of all 354 dependencies compiled into the binary, in
/usr/share/gpt-load/
Default user: ubuntu · Architecture: x86_64 · Root volume: 8 GiB gp3
Security posture
- No default credential and no baked provider key. The gate password, the auth key, the encryption key and the browser gate token are generated on each instance's first boot. None of them exists in the image, so no two instances share one, and no model provider key is ever shipped.
- Default-deny gate in front of every route. A key pool relay spends your provider credit, and GPT-Load's own authentication leaves some routes open by design (its health and integration endpoints, and the dashboard document for any path). So nginx enforces the gate at server scope: the dashboard, the admin API,
/healthand every/proxy/*relay path need this instance's credential. The only open location is nginx's own/nginx-healthliteral, which never reaches GPT-Load. - Fails closed. nginx will not start until first boot has proved, against this instance's real gate configuration, that an anonymous request gets
401and a one-character mutation of every credential is refused. Both units carry a preflight guard: GPT-Load refuses to start with an empty, short or default-looking auth key or a non-loopback bind, and nginx refuses an empty or plaintext gate file. - Only nginx faces the network. It answers only for the configured hostname (any other
Hostheader gets its connection closed), uses TLS 1.2 or 1.3, refuses cross-originPOSTrequests and WebSocket upgrades (403), strips GPT-Load's CORS headers, and replaces any client-suppliedX-Forwarded-FororX-Real-IPwith the real peer address, so GPT-Load's request log records who really called it. - Your auth key never lands in a log. GPT-Load 1.4.12 no longer logs setting values or request query strings (upstream fix #863; 1.4.9 wrote the key into the journal). nginx logs paths without query strings, so the
?key=form is never recorded either. The cloudimg build proves that the auth key, encryption key, gate password and gate token appear nowhere in the journal,/var/logor any process command line. - The hostname comes from configuration, never from a request. First boot reads it from EC2 instance metadata (IMDSv2) or from
/etc/cloudimg/gpt-load-hostname. - No instance metadata access for the relay. A group's upstream address is whatever an administrator types in, and GPT-Load relays requests to it, so
gpt-load.serviceand nginx are blocked from the instance metadata service (169.254.169.254 and fd00:ec2::254) by systemdIPAddressDeny. The cloudimg build proves that a group pointed athttp://169.254.169.254cannot connect while a normal upstream works. Amazon Time Sync (169.254.169.123) is unaffected. - IMDSv2 required. The AMI is registered with
ImdsSupport v2.0, so instances launched from it refuse token-less (IMDSv1) metadata requests. - Patched dependencies. The upstream 1.4.12 release binary was built with Go 1.25.14 and older
golang.org/xmodules that carry known vulnerabilities (among them HTTP/2 denial-of-service issues). cloudimg compiles the same source with Go 1.26.9 and the smallest set of module updates that fixes them, and the build fails if any other dependency changes.govulncheckon the shipped binary reports only GO-2026-5932, which is in a package GPT-Load does not use and has no fix upstream. - Sandboxed service and per-instance identity.
gpt-load.serviceruns withNoNewPrivileges,ProtectSystem=full,ProtectHomeandPrivateTmp. SSH host keys and the machine ID are generated fresh on every instance.
Prerequisites
- An AWS account and permission to launch EC2 instances
- An EC2 key pair in the Region you launch in
- API keys for at least one model provider (OpenAI, Google Gemini, Anthropic or an OpenAI-compatible service)
Recommended instance type: m5.large. GPT-Load holds no model, so 2 vCPUs and 8 GiB of memory are ample; the model work happens at your providers.
Connecting to your instance
| Version | Operating system | SSH user |
|---|---|---|
| GPT-Load 1.4.12 on Ubuntu 24.04 | Ubuntu 24.04 LTS | ubuntu |
Step 1: Launch the instance
Option A: AWS Marketplace console
- Open the cloudimg Hardened Ollama, LiteLLM & Self Hosted LLM Server AMIs listing on AWS Marketplace and choose View purchase options, then Subscribe. One subscription covers every version in the listing.
- Once the subscription is active, choose Launch your software.
- Choose One-click launch from AWS Marketplace (or Launch from EC2 Console for the full launch wizard). In Version, choose GPT-Load 1.4.12 on Ubuntu 24.04, then choose your Region.
- Pick an instance type (
m5.largerecommended; the software charge is $0.04 per vCPU per hour) and your key pair. - Security group: the listing's default group opens SSH (22), HTTP (80) and HTTPS (443). Restrict SSH to your own IP address, and restrict 80 and 443 to the networks your applications and administrators use. This relay spends your provider credit.
- Choose your VPC and subnet, leave the metadata defaults (the image already requires IMDSv2), then choose Launch.
Option B: AWS CLI
Run this on your own workstation. It creates a security group that allows SSH from your management address and HTTPS from your application network, then launches the instance. Replace the AMI ID with the one shown for your Region on the Marketplace launch page, and the VPC, subnet, key pair and CIDR ranges with your own:
SG=$(aws ec2 create-security-group --group-name gpt-load-relay \
--description "GPT-Load relay" --vpc-id vpc-0123456789abcdef0 \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 443 --cidr 10.0.0.0/16
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 80 --cidr 10.0.0.0/16
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type m5.large \
--key-name my-key-pair \
--security-group-ids "$SG" \
--subnet-id subnet-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=gpt-load-relay}]'
You do not need --metadata-options: the AMI already makes IMDSv2 required.
Step 2: Connect and find your credentials
Connect as ubuntu with the key pair you chose:
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>
First boot finishes within a minute of launch. It sets the hostname GPT-Load is served as (the instance's public DNS name when it has one), creates the TLS certificate for it, generates the gate password, the auth key, the encryption key and the gate token, proves the gate refuses anonymous and wrong credentials, starts GPT-Load and nginx, and writes /root/gpt-load-credentials.txt (mode 0600, root). These are the entries in that file (the secret values are not shown here):
sudo grep -E '^GPTLOAD_(URL|GATE_USERNAME)=' /root/gpt-load-credentials.txt
sudo grep -oE '^[A-Z_]+=' /root/gpt-load-credentials.txt
sudo stat -c '%a %U:%G' /root/gpt-load-credentials.txt
GPTLOAD_URL=https://ec2-44-204-33-219.compute-1.amazonaws.com/
GPTLOAD_GATE_USERNAME=gptload
GPTLOAD_URL=
GPTLOAD_GATE_USERNAME=
GPTLOAD_GATE_PASSWORD=
GPTLOAD_AUTH_KEY=
GPTLOAD_ENCRYPTION_KEY=
600 root:root
| Value | What it is for |
|---|---|
GPTLOAD_URL |
The dashboard and relay address of this instance |
GPTLOAD_GATE_USERNAME |
The cloudimg gate's username for a browser (always gptload) |
GPTLOAD_GATE_PASSWORD |
The cloudimg gate's password for a browser, generated on this instance |
GPTLOAD_AUTH_KEY |
The one credential your applications use, and the dashboard's Auth Key |
GPTLOAD_ENCRYPTION_KEY |
Encrypts your pooled provider keys at rest. Keep it |
To read the values, run sudo cat /root/gpt-load-credentials.txt in your own session and store them in your secrets manager. Keep GPTLOAD_ENCRYPTION_KEY: your pooled provider keys are encrypted with it, and changing it without upstream's key migration makes the stored pool unreadable.
Step 3: Confirm the relay is running
The first-boot unit, GPT-Load and nginx are active, and only sshd and nginx listen beyond loopback. GPT-Load itself is on 127.0.0.1:3001, so the nginx gate is the only way in.
systemctl is-active gpt-load-firstboot.service gpt-load.service nginx.service
sudo ss -Htlnp | awk '{print $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort -u
curl -sk https://127.0.0.1/nginx-health
active
active
active
0.0.0.0:22 users:(("sshd"),("systemd"))
0.0.0.0:443 users:(("nginx"),("nginx"),("nginx"),("nginx"),("nginx"))
0.0.0.0:80 users:(("nginx"),("nginx"),("nginx"),("nginx"),("nginx"))
127.0.0.1:3001 users:(("gpt-load"))
127.0.0.53%lo:53 users:(("systemd-resolve"))
127.0.0.54:53 users:(("systemd-resolve"))
[::]:22 users:(("sshd"),("systemd"))
[::]:443 users:(("nginx"),("nginx"),("nginx"),("nginx"),("nginx"))
[::]:80 users:(("nginx"),("nginx"),("nginx"),("nginx"),("nginx"))
OK
/nginx-health is answered by nginx itself and reveals nothing about your configuration, so it is safe to use as a load balancer health check.
Step 4: Prove the gate
Anonymous requests to the dashboard, GPT-Load's health route, the admin API and the relay paths are all refused, and so is an auth key that is wrong by one character. This instance's own key is accepted in every form an SDK sends it:
for R in / /health /api/settings /api/groups /api/logs /proxy/default/v1/models; do
printf '%s -> %s\n' "$R" "$(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1$R)"
done
curl -sk -o /dev/null -w 'anonymous POST /proxy/default/v1/chat/completions -> %{http_code}\n' \
-X POST -H 'Content-Type: application/json' -d '{}' https://127.0.0.1/proxy/default/v1/chat/completions
K=$(sudo grep '^GPTLOAD_AUTH_KEY=' /root/gpt-load-credentials.txt | cut -d= -f2-)
curl -sk -o /dev/null -w 'wrong key -> %{http_code}\n' -K <(printf 'header = "Authorization: Bearer %sX"\n' "$K") https://127.0.0.1/api/settings
for H in "Authorization: Bearer" "X-Api-Key:" "X-Goog-Api-Key:"; do
curl -sk -o /dev/null -w "$H <key> -> %{http_code}\n" -K <(printf 'header = "%s %s"\n' "$H" "$K") https://127.0.0.1/api/settings
done
curl -sk -o /dev/null -w '?key=<key> -> %{http_code}\n' -K <(printf 'url = "https://127.0.0.1/api/settings?key=%s"\n' "$K")
/ -> 401
/health -> 401
/api/settings -> 401
/api/groups -> 401
/api/logs -> 401
/proxy/default/v1/models -> 401
anonymous POST /proxy/default/v1/chat/completions -> 401
wrong key -> 401
Authorization: Bearer <key> -> 200
X-Api-Key: <key> -> 200
X-Goog-Api-Key: <key> -> 200
?key=<key> -> 200
The gate accepts six equivalent proofs, all compared exactly and all unique to this instance:
| Proof | Who uses it |
|---|---|
HTTP Basic with GPTLOAD_GATE_USERNAME / GPTLOAD_GATE_PASSWORD |
Your browser, and curl -u |
A gate cookie issued after the browser signs in (Secure, HttpOnly, SameSite=Lax) |
Your browser, on every dashboard call |
Authorization: Bearer <auth key> |
The OpenAI SDK |
x-api-key: <auth key> |
The Anthropic SDK |
x-goog-api-key: <auth key> |
The Google GenAI SDK |
?key=<auth key> |
GPT-Load's native query form |
The last four are exactly the idioms GPT-Load's own authentication reads, so your application sends one credential that satisfies both the cloudimg gate and GPT-Load's own check.
Step 5: Open the dashboard
Browse to GPTLOAD_URL (https://<public-dns-name>/). The certificate is self-signed, so your browser warns once; accept it for this host (or install your own certificate, see Step 8). The browser then asks for a username and password: use GPTLOAD_GATE_USERNAME and GPTLOAD_GATE_PASSWORD. GPT-Load's own login page then asks for its Auth Key: paste GPTLOAD_AUTH_KEY.
The dashboard opens with nothing configured: no keys, no requests. That is exactly the state you receive, because this image never ships a provider key:

The footer may offer an update to a GPT-Load 2.0 release candidate; the 1.4 line is the current stable release and the one this version ships.
Step 6: Build your first key pool
The image ships with no group configured, and the relay's key store is encrypted with this instance's own key. You can confirm both from the shell:
K=$(sudo grep '^GPTLOAD_AUTH_KEY=' /root/gpt-load-credentials.txt | cut -d= -f2-)
curl -sk -K <(printf 'header = "Authorization: Bearer %s"\n' "$K") https://127.0.0.1/api/groups | jq -c .data
curl -sk -H 'Accept-Language: en' -K <(printf 'header = "Authorization: Bearer %s"\n' "$K") https://127.0.0.1/api/dashboard/encryption-status | jq -c .data
[]
{"has_mismatch":false,"message":"","scenario_type":"","suggestion":""}
has_mismatch: false means the key GPT-Load is running with is the key its stored data is encrypted with. Then, in the dashboard:
- Open Keys and choose Create Group.
- Give it a short, URL-safe name, for example
gemini. It becomes part of your endpoint URL. - Choose the Channel Type that matches the provider:
openai,geminioranthropic. - Set the Upstream Address to the provider's own API base, for example
https://generativelanguage.googleapis.comfor Gemini orhttps://api.openai.comfor OpenAI. - Save the group, then use Add Key to paste your API keys, one per line. This is the pool.

A group can also be an aggregate group of sub-groups with weights, which blends several providers behind one endpoint.
Step 7: Point your application at the relay
Your endpoint is https://<GPTLOAD_HOST>/proxy/<your-group-name> and your API key is GPTLOAD_AUTH_KEY. Copy the instance's certificate (/etc/ssl/gpt-load/gpt-load.crt) to your client and trust it, or put a certificate your clients already trust in front (Step 8).
With the OpenAI Python SDK, against a group of channel type openai:
from openai import OpenAI
client = OpenAI(
base_url="https://<GPTLOAD_HOST>/proxy/<your-group-name>/v1",
api_key="<GPTLOAD_AUTH_KEY>",
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)
With the Anthropic Python SDK, against a group of channel type anthropic:
from anthropic import Anthropic
client = Anthropic(
base_url="https://<GPTLOAD_HOST>/proxy/<your-group-name>",
api_key="<GPTLOAD_AUTH_KEY>",
)
With curl, against a group of channel type gemini:
curl --cacert gpt-load.crt "https://<GPTLOAD_HOST>/proxy/<your-group-name>/v1beta/models/gemini-2.0-flash:generateContent" \
-H "X-Goog-Api-Key: <GPTLOAD_AUTH_KEY>" -H 'Content-Type: application/json' \
-d '{"contents":[{"parts":[{"text":"Hello"}]}]}'
Everything after the group name is passed through to the provider unchanged: /proxy/gemini/v1beta/models/... becomes https://generativelanguage.googleapis.com/v1beta/models/... with one of your pooled keys attached.
Key health, rotation and blacklisting
- Rotation. Each request takes the next key from the pool, so load is spread across every key you own.
- Validation. Choose Validate on a group and GPT-Load tests every key in the pool against the upstream.
- Blacklisting. A key that fails repeatedly is moved out of rotation automatically, so a dead or rate-limited key stops failing your traffic; Restore all invalid puts them back, for example after a quota window resets.
Every relayed request is recorded on the Logs page with its group, the pooled key used, the status, the latency and the real client address:

Step 8: Serve GPT-Load under your own DNS name
Port 80 redirects to HTTPS on the configured hostname, and the certificate covers that name, the instance's public and private addresses, localhost and 127.0.0.1:
H=$(sudo grep '^GPTLOAD_URL=' /root/gpt-load-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' "http://$H/api/groups"
openssl x509 -in /etc/ssl/gpt-load/gpt-load.crt -noout -subject -enddate -ext subjectAltName
301 https://ec2-44-204-33-219.compute-1.amazonaws.com/api/groups
subject=CN = ec2-44-204-33-219.compute-1.amazonaws.com, O = cloudimg
notAfter=Jan 22 00:15:18 2029 GMT
X509v3 Subject Alternative Name:
DNS:ec2-44-204-33-219.compute-1.amazonaws.com, IP Address:44.204.33.219, IP Address:172.31.89.206, IP Address:127.0.0.1, DNS:localhost
To use your own name, point a DNS record at the instance (an Elastic IP keeps the address stable across stops), then run the helper. It records the name in /etc/cloudimg/gpt-load-hostname, issues a new self-signed certificate for it, updates the allowed origins and the credentials file, and reloads nginx. Then update Settings → Project address in the dashboard to match:
sudo gpt-load-set-hostname <your-dns-name>
For a publicly trusted certificate, put the instance behind an Application Load Balancer with an AWS Certificate Manager certificate, or replace /etc/ssl/gpt-load/gpt-load.crt and gpt-load.key with your own and run sudo systemctl reload nginx.
Step 9: Check the security controls
Both services carry the metadata block, nginx refuses cross-origin writes and requests for any hostname it was not configured with, and GPT-Load records the name of each setting it initialises but never its value:
systemctl show -p IPAddressDeny gpt-load.service nginx.service
H=$(sudo grep '^GPTLOAD_URL=' /root/gpt-load-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
K=$(sudo grep '^GPTLOAD_AUTH_KEY=' /root/gpt-load-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'cross-origin POST: %{http_code}\n' --cacert /etc/ssl/gpt-load/gpt-load.crt -K <(printf 'header = "Authorization: Bearer %s"\n' "$K") \
-X POST -H 'Origin: https://evil.example' -H 'Content-Type: application/json' -d '{}' "https://$H/api/groups"
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Host: evil.example' http://127.0.0.1/ || true); echo "unknown Host: ${code} (connection closed by nginx)"
sudo journalctl -u gpt-load.service --no-pager -o cat | grep 'Initialized system setting: proxy_keys' | tail -1 | sed -E 's/^time="[^"]*" //'
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
cross-origin POST: 403
unknown Host: 000 (connection closed by nginx)
level=info msg="Initialized system setting: proxy_keys"
The cloudimg build also proves, before the image is captured, that a group whose upstream is http://169.254.169.254 fails at the connection while a normal upstream answers, and that a request carrying a forged X-Forwarded-For is logged with the caller's real address by both nginx and GPT-Load.
Step 10: Where your data lives
/var/lib/gpt-load/data/gpt-load.db is the whole application state: your groups, your encrypted key pool, the settings and the request log. Only the gpt-load user can read it:
sudo stat -c '%a %U:%G %n' /var/lib/gpt-load/data
sudo ls /var/lib/gpt-load/data
700 gpt-load:gpt-load /var/lib/gpt-load/data
gpt-load.db
There is no database server and no cache server on this instance, so there is nothing else listening and nothing else to patch. To back it up, stop the relay and copy the directory together with the credentials file, because the database is unreadable without the encryption key (or take an EBS snapshot of the instance):
sudo systemctl stop gpt-load.service
sudo tar czf /root/gpt-load-backup-$(date +%F).tar.gz /var/lib/gpt-load/data /root/gpt-load-credentials.txt
sudo systemctl start gpt-load.service
Step 11: What is in the image, and under what licence
GPT-Load is MIT licensed, and the upstream licence ships with the image. The binary carries the upstream commit it was compiled from, and the build provenance records the exact dependency changes cloudimg made and the vulnerability scan of the shipped binary:
head -3 /usr/share/gpt-load/LICENSE.upstream
LC_ALL=C grep -a -o 'vcs\.revision=[0-9a-f]\{40\}' /usr/local/bin/gpt-load | head -1
cat /usr/share/gpt-load/build-provenance/go.mod.diff
grep -E '^Vulnerability #|affected' /usr/share/gpt-load/build-provenance/govulncheck.txt
MIT License
Copyright (c) 2024 GPT-Load Contributors
vcs.revision=18e8b7893d6b5da0ba43178d21fccba82a4674c0
-github.com/klauspost/compress v1.18.1
-go 1.25.0
-golang.org/x/crypto v0.52.0
-golang.org/x/net v0.55.0 // indirect
-golang.org/x/sync v0.21.0 // indirect
-golang.org/x/sys v0.45.0 // indirect
-golang.org/x/text v0.39.0
+github.com/klauspost/compress v1.18.7
+go 1.26.0
+golang.org/x/crypto v0.57.0
+golang.org/x/net v0.60.0 // indirect
+golang.org/x/sync v0.23.0 // indirect
+golang.org/x/sys v0.48.0 // indirect
+golang.org/x/text v0.42.0
Vulnerability #1: GO-2026-5932
Your code is affected by 1 vulnerability from 1 module.
Those seven lines are the only change to upstream's go.mod: golang.org/x/net and klauspost/compress were raised to their fixed releases, and Go's version selection requires the other golang.org/x modules and the go directive to follow. /usr/share/gpt-load/build-provenance/BUILD-PROVENANCE.txt lists the toolchain and every pinned download. GO-2026-5932 is in golang.org/x/crypto/openpgp, which GPT-Load does not use and for which no fixed version exists.
Every dependency compiled into the binary, the Go modules and the dashboard's npm packages, was licence-checked at build time. They are all permissive; there is no AGPL, SSPL, Business Source, Elastic Licence, Commons Clause or non-commercial component:
awk -F'\t' '$1=="go"||$1=="npm"{print $4}' /usr/share/gpt-load/dependency-licences.txt | sort | uniq -c | sort -rn | head -6
290 MIT
20 Apache-2.0
15 BSD
13 ISC
10 BSD-2-Clause
3 BSD-3-Clause
Maintenance
- Logs:
sudo journalctl -u gpt-load.service -ffor the relay,/var/log/nginx/for HTTPS access (paths only, never query strings). - Restart:
sudo systemctl restart gpt-load.service. - Operating system updates: Ubuntu's unattended security upgrades stay on, so nginx and the rest of the OS keep receiving patches. Apply the rest with
sudo apt update && sudo apt upgradein a maintenance window. - Upgrading GPT-Load: GPT-Load is a single binary at
/usr/local/bin/gpt-load. Upgrade deliberately to a newer stable release, back up/var/lib/gpt-load/datafirst, then restart the service. - Rotating the auth key: put the new value in
/etc/gpt-load/gpt-load.env(AUTH_KEY=), in the four key entries of/etc/nginx/conf.d/gpt-load-gate-map.confand in/root/gpt-load-credentials.txt, update Settings → Global proxy key in the dashboard, then restartgpt-load.serviceand reload nginx.
Troubleshooting
The browser keeps asking for a password. Use GPTLOAD_GATE_USERNAME and GPTLOAD_GATE_PASSWORD from /root/gpt-load-credentials.txt exactly, over https://. The dashboard's own login then wants GPTLOAD_AUTH_KEY.
nginx will not start. It is held on the gate markers and a preflight guard by design. Check what it refused:
sudo /usr/local/sbin/gpt-load-preflight.sh --nginx >/dev/null 2>&1; echo "exit=$?"
exit=0
First boot did not complete. Read its log with sudo journalctl -u gpt-load-firstboot.service --no-pager | tail -20.
Requests return an upstream error. No group or key has been added yet (Step 6), the group's upstream address is wrong, or every key in the pool has been blacklisted (check the group on the Keys page).
Support
cloudimg provides 24/7 support for this image by email and live chat: launching and connecting, key pools and providers, TLS and hostnames, and upgrades.
Trademarks
GPT-Load is developed by tbphp and the GPT-Load contributors. OpenAI, Gemini and Anthropic are trademarks of their respective owners. Ubuntu is a registered trademark of Canonical Ltd. All other product and company names are trademarks or registered trademarks of their respective holders. cloudimg is not affiliated with or endorsed by them.