NextChat
Overview
NextChat (formerly ChatGPT-Next-Web) is an open-source, self-hosted web interface for chatting with large language models. It gives a team one fast, private chat front end that talks to the model providers you already pay for, instead of routing conversations through somebody else's hosted product. You can organize conversations in a sidebar, pin reusable system prompts, pick from a built-in prompt template library, switch model or provider per conversation, and export or share a transcript. It is a progressive web app, so it installs to a desktop or phone home screen and works well on a small screen.
NextChat is a front end, not a model host. It calls an LLM provider API, so it runs comfortably on a small CPU-only VM and needs no GPU. It supports OpenAI and Azure OpenAI, Anthropic, Google Gemini, DeepSeek, Moonshot, Alibaba Qwen, ByteDance, iFlytek, xAI, ChatGLM and SiliconFlow, plus any OpenAI-compatible endpoint, so one deployment can front several providers at once.
This guide covers deploying and configuring NextChat on Ubuntu 24.04 on Azure, using SecureAnyCloud Azure Marketplace images. The image ships the free, open-source, MIT-licensed NextChat as the official upstream container, pinned by image digest and captured into the VM, so your instance starts in seconds and never silently upgrades.
No provider API key is ever baked into the image. NextChat's own access check is disabled whenever no access code is configured, so a unique 32-character access code is generated for each VM on first boot, and a preflight guard refuses to start the service without one.
NextChat is a trademark of its respective owner. This image is produced by SecureAnyCloud and is not affiliated with, endorsed by, or sponsored by the NextChat project. It ships the free, open-source, MIT-licensed, self-hosted software unmodified.
What you get:
- NextChat 2.16.1 (the MIT-licensed upstream container
yidadaa/chatgpt-next-web), pinned by image digest, not by a moving tag. - Docker Engine and the Compose plugin from the official Docker APT repository.
- The web UI published on port
80(mapped to the container's port3000). Nothing else is exposed. nextchat.serviceandnextchat-firstboot.serviceas systemd units, enabled and active on boot.- A unique 32-character access code generated per VM on first boot, never baked into the image.
- A fail-closed preflight guard: the service refuses to start if the access code is missing, empty or too short.
- Every LLM provider credential shipped empty. You always supply your own.
- MCP server-side tool execution left disabled, the upstream default.
- Ubuntu 24.04 LTS base with the latest security patches applied at build time.
- Azure Linux Agent for cloud integration and SSH key injection.
- 24/7 SecureAnyCloud support with a guaranteed 24-hour response SLA.
Prerequisites
- An active Azure subscription, an SSH public key, and a VNet and subnet in the target region.
- A subscription to the NextChat listing on Azure Marketplace.
- An API key for at least one LLM provider (OpenAI, Anthropic, Google Gemini, DeepSeek and others are supported). SecureAnyCloud does not supply one and never bundles one.
- Recommended virtual machine size:
Standard_B2s(2 vCPU, 4 GB RAM) is ample. NextChat is a single prebuilt Node.js server with no database and no local model, so it idles at roughly 150 MB of memory. Increase the size only for a large number of concurrent conversations. - NSG inbound rules: allow
22/tcpfrom your management network and80/tcpfor the web UI from the networks that use it.
Deploy from the Azure Portal
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for NextChat by SecureAnyCloud, and select Create. On Basics, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80). Then select Review + create and Create.
Deploy from the Azure CLI
RG="nextchat-prod"; LOCATION="eastus"; VM_NAME="nextchat-01" IMAGE_URN="sac1647283583153:nextchat-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name nc-vnet --address-prefix 10.100.0.0/16 --subnet-name nc-subnet --subnet-prefix 10.100.1.0/24 az network nsg create -g "$RG" --name nc-nsg az network nsg rule create -g "$RG" --nsg-name nc-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name nc-nsg --name allow-http --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:nextchat-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name nc-vnet --subnet nc-subnet --nsg nc-nsg --public-ip-sku StandardConnect to your VM
ssh azureuser@<vm-ip>Confirm the services are running
NextChat runs as one container under nextchat.service, published on host port 80. Confirm that the services are active and view the container:
sudo systemctl is-active docker nextchat-firstboot nextchat
sudo docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'All three services report active, and the container is Up with only 0.0.0.0:80->3000/tcp published:
active active active NAMES STATUS PORTS nextchat Up About a minute 0.0.0.0:80->3000/tcp, [::]:80->3000/tcpRead the per instance access code
First boot generated a unique 32-character access code for this VM, before the app was reachable, and wrote it to a root-only file. Read it:
sudo cat /root/nextchat-credentials.txtThe file (mode 0600 root:root) holds NEXTCHAT_URL and NEXTCHAT_ACCESS_CODE. Neither ships in the image. The code is unique to this VM, so no two instances share one and there is no default to change.
Understand the access code security model
This is the most important section of this guide. NextChat protects a server-side provider key with an access code. Its own rule is that the check is enabled only when at least one code is configured. An empty access code therefore silently turns the gate off, and an instance with a working provider key would let anyone who finds the address spend your credits.
This image closes that gap. The code is generated per VM, and nextchat.service runs a preflight guard that refuses to start without one.
Confirm that the gate is on and that requests without a valid code are refused:
B=http://localhost curl -s $B/api/config | jq '{needCode, hideUserApiKey, disableGPT4}' curl -s -o /dev/null -w 'no access code: HTTP %{http_code}\n' -X POST \
-H 'Content-Type: application/json' -d '{"model":"gpt-4o-mini","messages":[]}' \
$B/api/openai/v1/chat/completions curl -s -X POST -H 'Content-Type: application/json' \
-d '{"model":"gpt-4o-mini","messages":[]}' $B/api/openai/v1/chat/completions | jq -c . curl -s -o /dev/null -w 'wrong access code: HTTP %{http_code}\n' -X POST \
-H 'Content-Type: application/json' -H 'Authorization: Bearer nk-not-the-code' \
-d '{"model":"gpt-4o-mini","messages":[]}' $B/api/openai/v1/chat/completions curl -s -X POST -H 'Content-Type: application/json' -H 'Authorization: Bearer nk-not-the-code' \
-d '{"model":"gpt-4o-mini","messages":[]}' $B/api/openai/v1/chat/completions | jq -c .needCode is true (the gate is enabled), and both an absent and a wrong access code are refused with 401:
{ "needCode": true, "hideUserApiKey": false, "disableGPT4": false } no access code: HTTP 401 {"error":true,"msg":"empty access code"} wrong access code: HTTP 401 {"error":true,"msg":"wrong access code"}Send the same request again with your access code from Step 5:
CODE='<NEXTCHAT_ACCESS_CODE>' curl -s -X POST -H 'Content-Type: application/json' \
-H "Authorization: Bearer nk-${CODE}" \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"ping"}]}' \
http://localhost/api/openai/v1/chat/completions | jq -c .Before you set a provider key, the reply is no longer a NextChat refusal. It is an error from the provider itself, which shows that the access code was accepted and your request was forwarded:
{"error":{"message":"Incorrect API key provided: nk-...","type":"invalid_request_error","param":null,"code":"invalid_api_key"}}An "error": true with a "msg" field means NextChat is refusing you. An "error" object with a "message" field means your provider is answering. Step 7 supplies the key that turns this into a real model response.
Supply your own LLM provider API key
SecureAnyCloud never ships a provider key. There are two ways to supply yours.
Option A: each person brings their own key (no server configuration). Open the web UI, go to Settings, and paste a personal API key into the provider key field. Requests then use that person's key and their own billing. Nothing needs to change on the VM.
Option B: one key for everyone on this VM. Set the key once in the environment file. Edit /var/lib/nextchat/.env with sudo nano /var/lib/nextchat/.env and fill in the provider you use:
# one of these, matching your provider OPENAI_API_KEY=<your-token> BASE_URL=https://api.openai.com
# or Anthropic ANTHROPIC_API_KEY=<your-token>
# or Google Gemini GOOGLE_API_KEY=<your-token>Restart the service to apply the change:
sudo systemctl restart nextchat.serviceWith Option B, the key lives only on your VM, and the access code from Step 5 is what stops anyone else from using it. Any OpenAI-compatible endpoint works: point BASE_URL at it and set OPENAI_API_KEY to that service's key.
The environment file is the whole configuration surface. Every provider credential ships empty:
sudo grep -vE '^\s*#' /var/lib/nextchat/.env | grep -v '^$' \
| sed -E 's|^(CODE=).*|\1<generated on this VM at first boot>|'CODE=<generated on this VM at first boot> OPENAI_API_KEY= <set-at-first-boot>=https://api.openai.com OPENAI_ORG_ID= ANTHROPIC_API_KEY= <set-at-first-boot>= ANTHROPIC_URL= GOOGLE_API_KEY= <set-at-first-boot>= DEEPSEEK_API_KEY= <set-at-first-boot>= SILICONFLOW_URL= ENABLE_MCP= HIDE_USER_API_KEY= <set-at-first-boot>= DISABLE_GPT4= DISABLE_FAST_LINK= CUSTOM_MODELS= DEFAULT_MODEL=Open the web UI and enter the access code
Browse to http://<vm-ip>/ to reach NextChat. Open Settings and paste the NEXTCHAT_ACCESS_CODE from Step 5 into Access Code. The panel confirms Access control Enabled. This is also where a user pastes their own provider key if you chose Option A in Step 7.
Start a conversation
Close Settings to reach the conversation workspace: the conversation list on the left, the message pane in the middle, and the composer at the bottom. Select New Chat to start a fresh conversation at any time.
Type a message and select Send. The reply streams back into the conversation and renders as formatted markdown, with the model name shown above it. Your message goes from the browser to NextChat on your VM, out through its server-side provider proxy to the model provider you configured, and the reply comes back and renders here.
Use the prompt template library
Choose Mask in the sidebar to open the built-in Prompt Template library. It holds reusable system prompts that pre-configure a conversation for a task, each with its own model and settings. Filter by language or search, select Chat to start a conversation from a template, or select Create to save your own.
Confirm the pinned release and its license
The container is pinned by image digest, not by a moving tag, so your instance ships an exact, reproducible artifact. The image's own OCI labels record the upstream release, its license and the exact source commit it was built from:
NC_IMAGE='yidadaa/chatgpt-next-web@sha256:eaaa469ddeeb5fa58fb35f8767e9e096a2f1c8468c54b6703323624bf3071c5a'
sudo docker inspect --format '{{json .Config.Labels}}' "$NC_IMAGE" | jq '{ version: ."org.opencontainers.image.version", licence: ."org.opencontainers.image.licenses", source: ."org.opencontainers.image.source", revision:."org.opencontainers.image.revision"}'{ "version": "v2.16.1", "licence": "MIT", "source": "https://github.com/ChatGPTNextWeb/NextChat", "revision": "557a2cce357749c6fb3176d42e03ff6f7de4d355" }Confirm the fail closed guard
nextchat.service runs a preflight guard before every start. If the access code is ever removed, emptied or shortened, the service refuses to start rather than come up ungated. Confirm that the guard is wired in, and see it refuse:
sudo systemctl show -p ExecStartPre --value nextchat.service | head -1 printf 'CODE=\n' | sudo tee /tmp/demo.env >/dev/null
sudo /usr/local/sbin/nextchat-preflight.sh /tmp/demo.env; echo "exit=$?"
sudo rm -f /tmp/demo.envThe unit shows the guard in its ExecStartPre, and the guard exits 1 on an empty access code:
exit=1 nextchat-preflight: REFUSING TO START — CODE is empty in /tmp/demo.env. NextChat would run with NO access-code gate, leaving any configured provider key open to the internet. Set a long random CODE and try again.Rotate the access code
The access code is a shared secret for this instance. To roll it, write a new long random value and restart the service:
NEW_CODE="$(openssl rand -base64 64 | tr -dc 'A-Za-z0-9' | cut -c1-32)" sudo sed -i "s|^CODE=.*|CODE=${NEW_CODE}|" /var/lib/nextchat/.env
sudo sed -i "s|^NEXTCHAT_ACCESS_CODE=.*|NEXTCHAT_ACCESS_CODE=${NEW_CODE}|" /root/nextchat-credentials.txt
sudo systemctl restart nextchat.service
sudo systemctl is-active nextchat.serviceEveryone then re-enters the new code in Settings. CODE accepts a comma-separated list, so you can also issue a different code per person and revoke one without disturbing the others.
Server components
The image contains these components:
- Application: NextChat 2.16.1 (yidadaa/chatgpt-next-web), pinned by image digest.
- Upstream source: github.com/ChatGPTNextWeb/NextChat, commit 557a2cce (git tag v2.16.1).
- Runtime: Node.js 18 (prebuilt Next.js standalone server) inside the container.
- Front door: container port 3000, published on host :80.
- Orchestration: Docker Compose under nextchat.service.
- Access code: per instance, 32 characters, generated on first boot into /var/lib/nextchat/.env and /root/nextchat-credentials.txt.
- Fail-closed guard: /usr/local/sbin/nextchat-preflight.sh as the unit's ExecStartPre.
- Provider credentials: none shipped. You supply them in /var/lib/nextchat/.env, or each user supplies one in the browser.
- Server-side data: none. Conversations are stored in the browser.
- MCP tool execution: disabled (ENABLE_MCP empty, the upstream default).
- Operating system: Ubuntu 24.04 LTS (patched at build).
- License: MIT (NextChat).
Managing the service
sudo systemctl status nextchat --no-pager | head -12 sudo docker compose -f /var/lib/nextchat/docker-compose.yml logs --tail 40 nextchatRestart the app with sudo systemctl restart nextchat.service, follow the logs live with sudo docker compose -f /var/lib/nextchat/docker-compose.yml logs -f nextchat, and view the configuration in /var/lib/nextchat/.env. After changing the environment file, restart the service to apply the change.
Conversations are stored in the browser, not on the server, so there is no server-side database to back up. Each user can export their conversations from the NextChat UI.
Use your own domain and HTTPS (production)
The image serves the web UI over plain HTTP on port 80, which is convenient behind a load balancer or private network. For production, terminate TLS in front of the VM so that the access code and your conversations travel encrypted:
- Front the VM with Azure Application Gateway, a load balancer with a managed certificate, or a CDN, and forward to the app on port
80. - Keep the NSG rule for port
80restricted to the front door, not the whole internet.
Security recommendations
- Restrict the NSG. Allow TCP 80 (and 22 for admin) only from the networks that use the app. The access code is the application-level control and the NSG is the network-level one. You want both.
- Terminate TLS in front of the app (Step 16) so that the access code and conversation content are encrypted in transit.
- Rotate the access code (Step 13) when someone leaves. To revoke codes individually, issue per-person codes using the comma-separated list.
- Never remove the access code. The service refuses to start without one, which is deliberate: an ungated instance with a provider key configured is an open relay on your credits.
- Set a provider key rather than leaving one unset. With the access code accepted but no server-side key configured, NextChat forwards your request to the provider using the access code as the API key, so the code reaches your provider in a failed request. Configure a real key in Step 7, or have each user supply their own in the browser, to avoid that.
- Consider
HIDE_USER_API_KEY=1if you want everyone to use the server key only and to stop users supplying their own in the browser. - Leave MCP disabled unless you specifically need it. Enabling it lets the server execute tools on this VM.
- Watch your provider spend. The access code protects the key, but anyone holding the code can spend on it. Set a usage limit in your provider's console.
- Keep the OS patched. Unattended security upgrades remain enabled on the running VM.
Support and Licensing
NextChat is distributed under the MIT License. This SecureAnyCloud image bundles the unmodified official open-source release, pinned by image digest. SecureAnyCloud provides the packaging, the per-instance access code generation, the fail-closed service guard, the paired deploy guide, and 24/7 support with a guaranteed 24-hour response SLA.
There is no per-user or per-seat software fee. You pay your own model provider directly for token usage. NextChat is an independent open-source project, and this image is not affiliated with or endorsed by it.
Deploy on Azure
Deploy on Azure
Launch NextChat on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
NextChat is an open-source, self-hosted web interface for chatting with large language models. It gives a team one fast, private chat front end that talks to the model providers you already pay for, instead of routing conversations through somebody else's hosted product.
This image runs NextChat 2.16.1 (ChatGPTNextWeb/NextChat, MIT) on Ubuntu 24.04 LTS. NextChat runs as the official upstream container under Docker, pinned by image digest so the deployment is reproducible and never silently upgrades. The container publishes on port 80. The default security group opens port 22 (SSH) and port 80 (HTTP) only.
This image contains no model and no inference
NextChat is a front end, not a model host. This image ships no model weights, no inference engine, no API key and no model credits. You bring your own model provider account. Every prompt you send is delivered to the provider you configure, and that provider bills you directly for token usage.
NextChat supports OpenAI and Azure OpenAI, Anthropic, Google Gemini, DeepSeek, Moonshot, Alibaba Qwen, ByteDance, iFlytek, xAI, ChatGLM, SiliconFlow and any OpenAI-compatible endpoint, so one deployment can front several providers at once. Because NextChat is CPU-only with no model to load, it runs comfortably on a small instance and needs no GPU.
The access code gate ships ENABLED
The access code gate is the main security control on this image, so it is worth understanding.
NextChat gates server-side provider access on a CODE value, but its own logic fails open. It derives "is a code required?" from how many codes are configured, so an empty CODE silently switches the gate off. An instance in that state, with a working provider key set, would let anyone who finds the address spend your provider credits.
SecureAnyCloud closes that gap in two places:
- On the first boot of every deployed instance, a one-shot service generates a fresh 32-character access code, unique to that instance, and writes it to
/root/nextchat-credentials.txt(mode0600, root only). It is never a fixed or shared value, and it is never baked into the image. nextchat.servicecarries anExecStartPrepreflight guard that refuses to start the service at all if the access code is missing, empty, shorter than 24 characters, or a well-known default value.
So there is no default login to change, and no window in which the instance runs ungated.
Where your data goes
"Self-hosted" does not mean "nothing leaves the instance". Here is where your data lives:
- Stays on your instance: the NextChat application, its configuration, and any provider key you set on the server.
- Stays in the browser: conversation history. NextChat keeps chat history in browser storage, not in a server-side database, so there is no chat database on the instance to back up.
- Leaves your instance: the prompts themselves. They go to whichever model provider you configure, over that provider's API, under that provider's terms. Self-hosting the interface does not make the prompts private from your provider.
Storage layout
One dedicated EBS volume keeps the container image store off the operating system disk, and you can resize it independently:
- /var/lib/docker: Docker data-root, holding the digest-pinned NextChat image.
- /var/lib/containerd: bind-mounted to /var/lib/docker/containerd-store. Docker 29 keeps image layers in the containerd store, so this must live on the same dedicated volume or the layers land back on the operating system disk.
Both are recorded in /etc/fstab (the data volume by filesystem UUID), so the layout reproduces on every instance you launch. There is no application data volume, because NextChat holds chat history in the browser and keeps no server-side database.
Connecting to your instance
The SSH login user for Ubuntu 24.04 LTS is ubuntu. Connect with:
- ssh -i /path/to/key.pem ubuntu@<public-ip>
Use these commands and addresses for the main tasks:
- The per-instance access code: sudo cat /root/nextchat-credentials.txt on the instance.
- The web interface: http://<public-ip>/ in a browser.
- Provider configuration file: sudo nano /var/lib/nextchat/.env, then sudo systemctl restart nextchat.service.
The credentials file is mode 0600 and owned by root, so it is readable only with sudo.
Launching the instance
In the AWS Marketplace console, choose the listing, then select Continue to Subscribe, Continue to Configuration and Continue to Launch. Pick your instance type (m5.large is the recommended size), your key pair and a security group.
Restrict inbound port 80 to your own networks. The chat interface is served over plain HTTP on port 80. The access code gate protects your provider credits, but it is not a substitute for network controls or TLS. See Putting TLS in front below.
To launch from the AWS CLI instead, substitute your own AMI id, key pair, subnet and security group:
- Launch: aws ec2 run-instances --image-id <ami-id> --instance-type m5.large --key-name <key-name> --security-group-ids <sg-id> --subnet-id <subnet-id>
- Find the address: aws ec2 describe-instances --instance-ids <instance-id> --query 'Reservations[0].Instances[0].PublicIpAddress' --output text
First run
First boot takes a minute or so while the access code is generated and the container starts. Check that both services are up:
systemctl is-active docker.service nextchat.serviceConfirm the container is running the digest-pinned image and publishing on port 80:
cd /var/lib/nextchat && sudo docker compose psThe image is pinned by digest, so you can verify exactly which upstream release you are running from the image's own labels:
sudo docker image inspect yidadaa/chatgpt-next-web@sha256:eaaa469ddeeb5fa58fb35f8767e9e096a2f1c8468c54b6703323624bf3071c5a --format 'version={{index .Config.Labels "org.opencontainers.image.version"}} licence={{index .Config.Labels "org.opencontainers.image.licenses"}} revision={{index .Config.Labels "org.opencontainers.image.revision"}}'The revision is the upstream git commit that the release tag points at, and the license label is the upstream project's own declaration.
Confirm the access code gate is on
/api/config is what the browser reads to decide whether to ask for an access code. needCode must be true:
curl -s http://127.0.0.1/api/config | jq .Prove it for yourself. A chat request with no credentials is refused by the gate, with a specific error, before it ever reaches a provider:
curl -s -o /tmp/nc-check.json -w 'HTTP %{http_code}\n' --max-time 30 -X POST -H 'Content-Type: application/json' -d '{"model":"gpt-4o-mini","stream":false,"messages":[{"role":"user","content":"ping"}]}' http://127.0.0.1/api/openai/v1/chat/completions; cat /tmp/nc-check.json; rm -f /tmp/nc-check.jsonThe reply is HTTP 401 with the body {"error":true,"msg":"empty access code"}. The exact body is the important part. An HTTP status alone is not proof, because a request that passes the gate and reaches an unconfigured provider also comes back 401, with the provider's own error object instead. The "msg":"empty access code" marker tells you the gate itself did the refusing.
Check that the fail-closed preflight guard is attached to the service:
systemctl show -p ExecStartPre --value nextchat.serviceRetrieve your access code
Read the credentials file over SSH (see Connecting to your instance above for the exact command). It contains the instance URL and the access code. You can confirm that a code was generated without printing it:
sudo awk -F= '/^NEXTCHAT_ACCESS_CODE=/{printf "access code present: %d characters\n", length($2)}' /root/nextchat-credentials.txtOpen http://<public-ip>/ in a browser, go to Settings, and paste the code into Access Code.
Connecting your own model provider
You have two options, and they can be mixed.
Per person, in the browser. Each user opens Settings and pastes their own provider API key into the key field. Nothing is stored on the server. This is the best fit when people already hold their own provider accounts.
Once, for the whole instance. Edit /var/lib/nextchat/.env on the instance, set the key for the provider you use, and restart the service. The file is mode 0600 and owned by root.
- Edit the configuration: sudo nano /var/lib/nextchat/.env
- Apply it: sudo systemctl restart nextchat.service
You can see which settings the file exposes without revealing any value:
sudo grep -oE '^[A-Z_]+=' /var/lib/nextchat/.env | tr '\n' ' '; echoConfirm for yourself that no provider key ships in this image. This command counts the provider key entries that have a value. On a freshly launched instance, the count is 0:
sudo awk -F= '/^[A-Z0-9_]*API_KEY=./{n++} END{printf "provider API keys with a value: %d\n", n+0}' /var/lib/nextchat/.envBASE_URL points at the upstream provider endpoint by default. Set it to your own OpenAI-compatible endpoint (a local gateway, a proxy, or another vendor) to route through that instead.
Server-side tool execution (ENABLE_MCP) is left disabled, as upstream ships it, so the image does not execute tools on the instance out of the box.
Using NextChat
Conversations live in the left sidebar. Start a new one with New Chat, and switch model or provider per conversation from the chat toolbar.
Prompt templates ("masks") let you pin a reusable system prompt and a model with its parameters, and start new conversations from them. The image ships the upstream template library. Starting a new chat offers the template picker first, or you can skip straight to a blank conversation.
The interface is a progressive web app, so it installs to a desktop or phone home screen from the browser and works well on a small screen.
Storage and operations
Confirm the container image store is on the dedicated volume rather than the operating system disk:
df -h / /var/lib/dockerDocker 29 keeps image layers in the containerd store, so check that it resolves to the same device:
findmnt -no SOURCE,TARGET /var/lib/containerd; df --output=source /var/lib/docker /var/lib/containerd | tail -2Both must report the dedicated volume. If they ever diverge, image layers are filling your operating system disk.
To resize the volume, grow the EBS volume in the AWS console, then extend the filesystem on the instance:
- Grow the filesystem: sudo resize2fs $(findmnt -no SOURCE /var/lib/docker)
Check which ports are actually served:
ss -tlnH | awk '{print $4}' | sort -uOnly 22 and 80 are exposed beyond loopback. The entries on 127.0.0.53 and 127.0.0.54 are the systemd resolver, which is loopback only.
View the service logs with these commands:
- Service unit: sudo journalctl -u nextchat.service -n 100 --no-pager
- First boot: sudo journalctl -u nextchat-firstboot.service -n 100 --no-pager
- Container: cd /var/lib/nextchat && sudo docker compose logs --tail 100 nextchat
Changing the access code
Set a new value for CODE in /var/lib/nextchat/.env and restart the service. CODE accepts a comma-separated list, so you can issue several codes and revoke one without disturbing the others.
- Edit: sudo nano /var/lib/nextchat/.env
- Apply: sudo systemctl restart nextchat.service
The preflight guard enforces a minimum of 24 characters and rejects well-known default values. If the service refuses to start after an edit, that guard is the reason. Run sudo journalctl -u nextchat.service -n 20 --no-pager to see it.
Removing the access code entirely is not a supported configuration. The service refuses to start rather than run as an open relay.
Putting TLS in front
The image serves plain HTTP on port 80. Before exposing an instance beyond a trusted network, terminate TLS in front of it. Two straightforward options:
- An AWS Application Load Balancer with an ACM certificate, forwarding to the instance on port 80, with the instance's security group accepting port 80 only from the load balancer.
- A reverse proxy on the instance (nginx or Caddy) holding the certificate and proxying to the container. The container publishes on host port 80, so move that mapping in
/var/lib/nextchat/docker-compose.ymlbefore binding a proxy to 80.
In either case, also restrict the security group to your own network ranges.
Licensing and support
NextChat is MIT licensed, so there is no per-user or per-seat software fee. The image ships the upstream release pinned by digest. The license label above is the upstream project's own declaration for exactly the artifact that runs here.
The SecureAnyCloud charge covers packaging, security hardening, patching, image maintenance and support. You pay your model provider directly for token usage.
NextChat is an independent open-source project. This image is produced by SecureAnyCloud and is not affiliated with or endorsed by the NextChat project.
Support
SecureAnyCloud provides 24/7 support by email at sales@secureanycloud.com and via live chat at secureanycloud.com. We aim to respond within one business day.
Support covers deployment of this image, the access code gate, service and container health, operating system patching, and configuring the image against your own model provider. Model provider accounts, API keys and token billing remain with your chosen provider.
Deploy on AWS
Launch NextChat on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com