Running the Nextcloud Talk AIO Container as a Standalone High-Performance Backend

Table of Contents đ
- Changelog
- 1. Prerequisites
- 2. Create the project directory and secrets
- 3. Create the Docker Compose file
- 4. Start and verify the backend
- 5. Configure Nextcloud Talk
- 6. Test a real call
- 7. Maintenance and updates
- 8. Running multiple independent Nextcloud instances
- 9. Recording backend scope
- 10. Troubleshooting
- Conclusion
- Related tutorials
This guide deploys the official pre-built Nextcloud Talk container as a standalone High-Performance Backend (HPB). It is intended for an existing, non-AIO Nextcloud installation and does not migrate Nextcloud, its database, files, or reverse proxy to Nextcloud All-in-One.
The container bundles the components needed for a modern Talk backend: the signaling server, Janus media gateway, NATS, and an integrated TURN service. Compared with maintaining the classic multi-container signaling stack yourself, it removes the custom builds and most component-level configuration.
It follows the upstream Nextcloud Talk quick-install documentation and uses the pre-built image maintained in the Nextcloud AIO project.
| âšī¸ WHAT THIS GUIDE INSTALLS |
This is the AIO Talk container only, not the complete Nextcloud AIO appliance. Your existing Nextcloud Docker Compose stack stays in place and is configured to use this backend afterwards. |
Changelog
| Date | Change |
|---|---|
| 2026-09-06 | Initial Version: Added the standalone AIO Talk container tutorial. |
1. Prerequisites
This guide assumes that you already have:
- A working Nextcloud instance with the Talk app enabled.
- Docker Engine and Docker Compose v2.
- A Traefik v3 reverse proxy with a shared external Docker network named
proxy. - A dedicated DNS name for the signaling and TURN service, such as
talk.example.com, pointing to the Docker host. - A valid TLS certificate for that DNS name.
sudoor root access on the Docker host.
The reverse-proxy setup from the following guide is a suitable foundation:
- Traefik v3 and CrowdSec with Docker Compose: A Modern Security Stack
- Debian Server Initial Setup for a baseline host and firewall configuration.
For Docker Compose fundamentals and reverse-proxy behavior, refer to the Docker Compose documentation and the Traefik documentation. If your Nextcloud instance is already behind a proxy, also verify the Nextcloud reverse-proxy settings.
| â ī¸ ONE CONTAINER, ONE NEXTCLOUD BACKEND |
The standalone AIO Talk container creates one configured signaling backend from |
1.1. Firewall configuration
The reverse proxy handles HTTPS on ports 80 and 443. The integrated TURN server must be reachable directly on the Talk port over both TCP and UDP. The examples use 3478.
sudo ufw allow 3478/tcp
sudo ufw allow 3478/udpIf your firewall is managed by a cloud provider or hardware router, open and forward the same two ports there as well.
| âšī¸ TURN IS NOT HTTP TRAFFIC |
The TURN port bypasses Traefik and its HTTP middleware. Keep the Talk container updated, use a long random TURN secret, and restrict host access with your firewall policy where appropriate. |
2. Create the project directory and secrets
Create a dedicated directory for the backend. Keeping the .env file separate prevents secrets from being committed or copied into a public Compose example.
sudo mkdir -p /opt/containers/nextcloud-aio-talk
cd /opt/containers/nextcloud-aio-talk
sudo chmod 700 .Generate three independent secrets:
openssl rand -hex 32
openssl rand -hex 32
openssl rand -hex 32Create .env and replace every placeholder. NC_DOMAIN and TALK_HOST are host names only, without https:// or a path.
sudo tee .env > /dev/null << 'EOF'
# Existing Nextcloud instance that will use this container
NC_DOMAIN=cloud.example.com
# Public DNS name for signaling and TURN
TALK_HOST=talk.example.com
# Keep all three values private and use different random values.
TURN_SECRET=REPLACE_WITH_A_RANDOM_64_HEX_CHARACTER_SECRET
SIGNALING_SECRET=REPLACE_WITH_A_RANDOM_64_HEX_CHARACTER_SECRET
INTERNAL_SECRET=REPLACE_WITH_A_RANDOM_64_HEX_CHARACTER_SECRET
EOF
sudo chmod 600 .envThe secrets have different roles:
| Secret | Purpose | Used in Nextcloud? |
|---|---|---|
SIGNALING_SECRET | Authenticates the Nextcloud server to the signaling backend. | Yes |
TURN_SECRET | Creates short-lived TURN credentials for Talk clients. | Yes |
INTERNAL_SECRET | Protects internal communication within the backend. | No |
| â ī¸ DO NOT REUSE PLACEHOLDER VALUES |
Never use the placeholder strings from this article. Generate unique random secrets for every Talk container and store the |
3. Create the Docker Compose file
The following Compose file uses Traefik for TLS and WebSocket forwarding. The TURN service is published directly on port 3478, while signaling remains internal and is exposed only through Traefik on port 8081.
sudo tee docker-compose.yml > /dev/null << 'EOF'
services:
talk:
image: ghcr.io/nextcloud-releases/aio-talk:latest
container_name: nextcloud-aio-talk
init: true
restart: unless-stopped
env_file:
- .env
environment:
# Required by the standalone AIO Talk image
TALK_PORT: "3478"
TURN_DOMAIN: ${TALK_HOST}
AIO_LOG_LEVEL: warn
SKIP_CERT_VERIFY: "false"
ports:
- "3478:3478/tcp"
- "3478:3478/udp"
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.nextcloud-aio-talk.rule=Host(`${TALK_HOST}`)"
- "traefik.http.routers.nextcloud-aio-talk.entrypoints=websecure"
- "traefik.http.routers.nextcloud-aio-talk.tls=true"
- "traefik.http.routers.nextcloud-aio-talk.middlewares=nextcloud-aio-talk-headers@docker,crowdsec-bouncer@docker"
- "traefik.http.middlewares.nextcloud-aio-talk-headers.headers.customRequestHeaders.X-Forwarded-Proto=https"
- "traefik.http.services.nextcloud-aio-talk.loadbalancer.server.port=8081"
networks:
proxy:
external: true
EOF| âšī¸ PATH PREFIXES |
The preferred layout is one dedicated signaling hostname per container. If a path prefix is unavoidable, add a Traefik |
4. Start and verify the backend
Pull the image and start the container:
cd /opt/containers/nextcloud-aio-talk
sudo docker compose pull
sudo docker compose up -d
sudo docker compose psVerify the public signaling endpoint. The response contains a version string and a welcome message:
curl https://talk.example.com/api/v1/welcomeCheck the container logs if the endpoint does not respond:
sudo docker logs --tail 100 nextcloud-aio-talkCommon causes of an unsuccessful start are a DNS record that does not point to the Docker host, a missing TLS certificate, port 3478 already being occupied, or an unreachable NC_DOMAIN from inside the container.
5. Configure Nextcloud Talk
Open Administration settings â Talk in Nextcloud and configure:
| Setting | Value |
|---|---|
| High-performance backend URL | https://talk.example.com |
| Shared secret | The value of SIGNALING_SECRET |
| TURN mode | turn: only |
| TURN server | talk.example.com:3478 |
| TURN secret | The value of TURN_SECRET |
| Protocols | UDP and TCP |
Save the settings and wait for the connection check to finish successfully.
5.1. Configure it using occ (optional)
The same configuration can be added from the Nextcloud container. Replace the placeholders before running the commands.
# Add the signaling endpoint and validate its TLS certificate
php occ talk:signaling:add --verify \
https://talk.example.com \
REPLACE_WITH_YOUR_SIGNALING_SECRET
# Add the integrated TURN service
php occ talk:turn:add \
turn \
talk.example.com:3478 \
udp,tcp \
--secret=REPLACE_WITH_YOUR_TURN_SECRETList configured endpoints with:
php occ talk:signaling:list
php occ talk:turn:list| â ī¸ MIGRATION FROM ANOTHER HPB |
Run the new backend alongside the old one first. Verify the new URL, configure it in Nextcloud, make a real test call from two different networks, and only then remove the old signaling entry and containers. Keep the old Compose directory until the migration has been verified. |
6. Test a real call
The welcome endpoint proves that Traefik can reach the signaling service, but it does not prove that media relay works. Create a Talk room and test a video call:
- Join from two separate devices or networks.
- Test microphone, camera, screen sharing, and reconnecting after a network change.
- Repeat the test from a mobile connection or a restrictive network to confirm TURN fallback.
During a test call, monitor the container:
sudo docker logs -f nextcloud-aio-talk7. Maintenance and updates
The image is intentionally pre-built, so normal updates do not require rebuilding Signaling, Janus, or NATS from source.
cd /opt/containers/nextcloud-aio-talk
sudo docker compose pull
sudo docker compose up -d
sudo docker image pruneBefore updating, back up the project directory, especially .env and docker-compose.yml:
sudo tar -C /opt/containers \
-czf nextcloud-aio-talk-backup-$(date +%F).tar.gz \
nextcloud-aio-talkReview release notes after updates and repeat the signaling endpoint and real-call checks. Do not use a blind docker image prune -a on a production host, as it may remove images used for rollback.
8. Running multiple independent Nextcloud instances
Each standalone AIO Talk container has exactly one NC_DOMAIN and one SIGNALING_SECRET. For two separate Nextcloud instances, use two isolated deployments.
| Item | First instance | Second instance |
|---|---|---|
| Project directory | /opt/containers/nextcloud-aio-talk-one | /opt/containers/nextcloud-aio-talk-two |
| Signaling hostname | talk-one.example.com | talk-two.example.com |
| Talk / TURN port | 3478 | 3479 |
| Container name | nextcloud-aio-talk-one | nextcloud-aio-talk-two |
NC_DOMAIN | cloud-one.example.com | cloud-two.example.com |
| Secrets | Three unique secrets | Three different unique secrets |
For the second deployment, copy the project directory, change every identifier shown above, and publish its configured TALK_PORT over TCP and UDP. Each Nextcloud instance then receives only its own signaling URL and its own Signaling and TURN secrets.
| â ī¸ NO SHARED SECRETS ACROSS TENANTS |
Do not share |
9. Recording backend scope
The AIO Talk image provides signaling, media handling, and TURN. It does not include the Talk Recording Backend. Recording is deployed as a separate service and should be planned, secured, and backed up independently.
Continue with Deploying the Nextcloud Talk AIO Recording Backend as a Standalone Container when you need recordings.
10. Troubleshooting
The High-Performance Backend check fails
- Verify DNS and TLS with
curl https://talk.example.com/api/v1/welcome. - Confirm that
SIGNALING_SECRETmatches exactly in.envand in Nextcloud Talk settings. - Confirm that
NC_DOMAINis the existing Nextcloud hostname without a scheme or path. - Inspect
sudo docker logs nextcloud-aio-talkfor certificate or connectivity errors.
Calls connect but media does not work
- Confirm that
3478/tcpand3478/udpare reachable from the internet. - Confirm the TURN hostname, port, secret, and UDP/TCP protocols in Talk settings.
- Test from an external mobile network, not only from the same LAN.
- Check provider firewalls and router port forwarding in addition to UFW.
The container cannot contact Nextcloud
- Ensure the Docker host can resolve and reach
https://cloud.example.com. - Use a publicly trusted certificate or mount an additional trusted CA certificate when using a private PKI.
- Do not set
SKIP_CERT_VERIFY=trueas a permanent workaround.
Conclusion
The standalone AIO Talk image is a practical way to use the maintained, pre-built Talk backend without replacing an existing Nextcloud deployment with full Nextcloud AIO. Keep each Nextcloud instance isolated, protect the secrets, verify TURN with real calls, and retain a tested rollback path during migration.
For the upstream quick-install procedure and current image details, see the official Nextcloud Talk documentation.





