IPTinCan Documentation
Everything you need to set up and run your own IPTinCan server — and everything about the managed hosting plans if we run it for you. Press / (or Ctrl/Cmd+K) anywhere on the site to search these docs, or ask the support assistant.
Getting Started
IPTinCan is private voice, video, and messaging on a server you control. It consists of two components:
- Server (
itc-server) — A C++ binary that handles connections, channels, messages, and data storage via SQLite. Voice and video calls run through a companion LiveKit service. - Client — A desktop app for Windows and Linux (macOS and mobile in development). It connects to your server over TCP (text/control); calls use LiveKit (WebRTC).
You can self-host the server for free (unlimited users), or subscribe to managed hosting and we run it for you.
Step-by-step guides: new to IPTinCan? Start with Set up a free server (zero to first call in ~10 minutes) or Add a server connection (joining a friend's server from the app).
Download & Install
Server
Managed-hosting servers are provisioned automatically when you subscribe — nothing to install. Self-hosting is free (unlimited users; grab a free license key on the setup guide):
- Debian/Ubuntu package — iptincan-server_amd64.deb: systemd service, dedicated user, config at
/opt/iptincan/server.toml. Install withsudo apt install ./iptincan-server_0.1.0-1_amd64.deb. - Portable binary — itc-server-linux-x64.tar.gz: extract and run
./itc-server; config and database live next to the binary.
Linux x64 today; a public Docker image and Windows build are planned. Voice/video calls additionally require a LiveKit server (see Voice & Video Calls).
Client App
The IPTinCan desktop app is available today for:
- Windows — Signed installer, or a portable .exe that needs no install. The installer build auto-updates in the background (a "Restart to update" banner appears; there's also a manual check in Settings).
- Linux — AppImage (x64). The AppImage does not auto-update — re-download from the site to upgrade.
- macOS, iOS, and Android — In development.
System Requirements: Server: Linux (Ubuntu 20.04+, Debian 11+) or Docker. 64-bit only, minimum 512 MB RAM. Client: Windows 10+ (64-bit) or Linux x64.
First Run
Starting the server
# Debian/Ubuntu package (runs as a service)
sudo systemctl status iptincan-server
# Portable binary
./itc-server
On first launch, the server will:
- Create a default
server.tomlconfiguration file in the working directory. - Initialize a SQLite database (
itc-server.db). - Create a default admin account (username:
chatter, password:chatter). - Start listening on TCP port 3784 (desktop clients), UDP port 3785 (media fallback), TCP port 3786 (REST API), and TCP port 3789 (WebSocket, used by the upcoming mobile apps).
Connecting with the client
Open the IPTinCan app. On the connect screen, you can enter your server details in one of two ways:
- Manual entry — Type the server address (e.g.,
chat.example.comor192.168.1.100) and port. - Invite or connection code — Paste an
ipt://invite link or anITC-code from the server's admin. See the Add a server connection guide for a walkthrough with screenshots.
Once connected, log in with the default credentials (chatter / chatter) or create a new account if registration is enabled.
Security Note: Change the default admin password immediately after first login. You can also change the default credentials in server.toml before first launch.
Server Setup
The server is a single binary that manages all connected clients, channels, and messages. It uses SQLite for persistent data storage, so there is no separate database to install or manage. Voice and video are handled by the LiveKit companion service (setup below) — text chat works without it.
Directory structure
iptincan/
itc-server # Server binary
server.toml # Server configuration (created on first run)
itc-server.db # SQLite database (plus .db-shm / .db-wal while running)
server-cert.pem # TLS certificate (if TLS enabled)
server-key.pem # TLS private key (if TLS enabled)
recordings/ # Recorded audio (if recording is used)
Configuration
The server is configured via server.toml. Here is a reference configuration with all available options and their defaults:
[server]
name = "My IPTinCan Server"
description = "A community chat server"
bind_address = "0.0.0.0"
tcp_port = 3784
udp_port = 3785
rest_port = 3786
ws_port = 3789 # WebSocket control plane (mobile clients)
max_users = 100
motd = "Welcome to IPTinCan!"
log_level = "info" # trace, debug, info, warn, error
shutdown_grace_seconds = 5
max_storage_bytes = 0 # 0 = unlimited
tags = ["gaming", "community"]
[database]
path = "itc-server.db"
[tls]
enabled = true
cert_path = "server-cert.pem"
key_path = "server-key.pem"
[auth]
allow_registration = true
session_ttl_seconds = 86400 # 24 hours
default_user = "chatter"
default_password = "chatter"
[livekit]
enabled = true # Required for voice/video calls
url = "ws://localhost:7880" # Client-facing LiveKit URL (wss:// in prod)
api_key = "" # Must match your livekit.yaml keys
api_secret = ""
e2ee = false # Optional end-to-end encryption for calls.
# Off by default: all clients in a call must
# support it (mobile apps don't yet).
[license]
key = "" # ITC-XXXX-XXXX-XXXX-XXXX (free — see Licensing)
server_url = "https://license.iptincan.com"
enforce = true
public_server = false # List on server browser (in development)
heartbeat_interval = 300 # Seconds
[google]
enabled = false
client_id = ""
client_secret = ""
callback_base_url = "http://localhost:3786"
[cluster]
enabled = false
role = "primary" # "primary" or "worker"
node_name = "node-1"
cluster_port = 3787 # Inter-node TCP
cluster_udp_port = 3788 # Inter-node UDP voice relay
cluster_secret = "" # Shared HMAC secret (min 16 chars)
primary_address = "" # Workers only: address of primary
primary_cluster_port = 3787
[vpn] # In development — see "In Development" below.
enabled = false # Server-side config exists, but current
subnet = "10.8.0.0/24" # apps can't enable the VPN yet.
dns_server = "1.1.1.1"
max_bandwidth_kbps = 0 # 0 = unlimited
tun_device_name = "itc-vpn0"
[notifications]
admin_email = ""
billing_worker_url = ""
billing_admin_token = ""
Port Forwarding: If hosting behind a router, forward TCP 3784 (clients), TCP 3786 (REST/OAuth), and TCP 3789 (WebSocket) to your server machine. For voice/video calls you also need the LiveKit ports — see Ports & Protocols for the full table.
TLS / SSL Setup
IPTinCan supports TLS 1.2+ for encrypted transport. There are three options for TLS certificates:
Option 1: Self-signed certificates
Generate a self-signed certificate using OpenSSL, then point the server at it. Clients will use trust-on-first-use (TOFU) fingerprint pinning to verify the server on subsequent connections.
# Generate a self-signed cert
openssl req -x509 -newkey rsa:4096 -keyout server-key.pem \
-out server-cert.pem -days 365 -nodes -subj "/CN=iptincan"
[tls]
enabled = true
cert_path = "server-cert.pem"
key_path = "server-key.pem"
Option 2: Let's Encrypt (recommended for public servers)
For servers with a domain name, use Let's Encrypt for free, trusted certificates:
- Install Certbot:
sudo apt install certbot - Obtain a certificate:
sudo certbot certonly --standalone -d chat.example.com - Configure the server:
[tls] enabled = true cert_path = "/etc/letsencrypt/live/chat.example.com/fullchain.pem" key_path = "/etc/letsencrypt/live/chat.example.com/privkey.pem" - Set up auto-renewal with a cron job:
0 0 1 * * certbot renew --quiet && systemctl restart itc-server
Option 3: Custom certificate
Use any PEM-format certificate and private key. Point cert_path and key_path to your files in server.toml.
Voice & Video Calls (LiveKit)
Text chat works the moment your server is up. Voice and video calls run through a companion LiveKit service (a WebRTC SFU): the IPTinCan server mints join tokens, and LiveKit carries the actual audio and video. Calls hold up to 8 participants.
You need two things wired together:
- A
livekit-serverinstance with alivekit.yamlconfig. - The
[livekit]section ofserver.tomlpointing at it, with matching API keys.
Quickest path: the Docker Compose stack below runs the server and LiveKit together with everything pre-wired. If you only need text to start, skip this and add calls later.
livekit.yaml essentials
port: 7880 # signaling (ws/wss)
keys:
myapikey: my_api_secret_at_least_32_characters
room:
max_participants: 8 # the product's call limit
empty_timeout: 300
auto_create: true
rtc:
port_range_start: 50000 # UDP media range
port_range_end: 50100
tcp_port: 7881 # RTC-over-TCP fallback
use_external_ip: true # advertise the public IP in ICE candidates
turn:
enabled: true # embedded relay for restrictive networks
udp_port: 3478
server.toml
[livekit]
enabled = true
url = "wss://chat.example.com:7880" # what CLIENTS connect to — a reachable
# address, not "localhost" or "livekit"
api_key = "myapikey"
api_secret = "my_api_secret_at_least_32_characters"
e2ee = false
The #1 calls gotcha: if use_external_ip is off (or node_ip isn't set to an address your clients can reach), LiveKit advertises an internal IP in its ICE candidates — calls work on the server machine and silently fail everywhere else. On a cloud host with a public IP, use_external_ip: true is all you need. On a LAN-only setup, set node_ip to the server's LAN address instead.
End-to-end encryption
All connections are TLS-encrypted regardless. Calls additionally support optional end-to-end encryption: set e2ee = true under [livekit] and restart. Every client in a call must support it — the desktop app does; the upcoming mobile apps don't yet — which is why it ships off by default.
Ports for calls
Open / forward: TCP 7880 (signaling), TCP 7881 (TCP fallback), UDP 3478 (TURN), and UDP 50000–50100 (media). "Calls don't connect" is almost always one of these blocked, or the ICE address gotcha above.
Docker Setup
Note: the public Docker image is not published yet — email support@iptincan.com for an early-access build. The compose file below shows how deployment works once it lands.
The recommended deployment is Docker Compose running both services — the IPTinCan server and LiveKit — with their keys wired together:
version: '3.8'
services:
itc-server:
image: iptincan/server:latest
container_name: iptincan-server
ports:
- "3784:3784" # TCP (text/control)
- "3785:3785/udp" # UDP media fallback
- "3786:3786" # REST API / OAuth callbacks
- "3789:3789" # WebSocket (mobile clients)
volumes:
- itc-data:/data
- ./server.toml:/app/server.toml:ro
environment:
# What the CLIENT connects to — your host's reachable address,
# not "livekit" or "localhost".
- LIVEKIT_URL=wss://chat.example.com:7880
- LIVEKIT_API_KEY=myapikey
- LIVEKIT_API_SECRET=my_api_secret_at_least_32_characters
depends_on:
- livekit
restart: unless-stopped
livekit:
image: livekit/livekit-server:latest
container_name: iptincan-livekit
command: --config /etc/livekit.yaml
ports:
- "7880:7880" # signaling (ws/wss)
- "7881:7881" # RTC over TCP fallback
- "3478:3478/udp" # embedded TURN
- "50000-50100:50000-50100/udp" # RTC media (bounded range)
volumes:
- ./livekit.yaml:/etc/livekit.yaml:ro
restart: unless-stopped
volumes:
itc-data:
The API key/secret in the environment must match the keys: entry in livekit.yaml (see Voice & Video Calls), and the secret must be at least 32 characters.
Important: publish the UDP ports with the /udp suffix — voice and video will not work without UDP connectivity. All IPTinCan server configuration is done via server.toml; the LIVEKIT_* environment variables are the only overrides.
Dynamic DNS
Hosting from a home connection usually means a dynamic IP address. IPTinCan offers a free subdomain with automatic IP updates so your people can always find your server.
Free IPTinCan subdomain
Servers with an active license — the $3/mo Licensed plan or any paid plan — can claim a free subdomain at <name>.servers.iptincan.com. Your server keeps the DNS record pointed at its current IP automatically.
- Names are 3–32 characters: lowercase letters, numbers, and hyphens. Some names are reserved.
- IP updates are rate-limited to one per 5 minutes.
- Managed-hosting servers get their
<name>.servers.iptincan.comaddress automatically — nothing to set up.
Third-party dynamic DNS
Self-hosted servers can also use any third-party dynamic DNS service (No-IP, DuckDNS, etc.) pointed at your server's IP. Clients then connect using the hostname instead of an IP.
Backups & Restore
Self-hosted
Everything lives next to the server binary. To back up, stop the server, then copy:
itc-server.db # the database
itc-server.db-shm # \ SQLite sidecar files
itc-server.db-wal # / (present while/after running)
recordings/ # recorded audio, if any
server.toml # your configuration
Restore by copying the files back and starting the server. A simple nightly cron job copying these files is plenty for a family server.
Never run an older server version against a newer database. Upgrading migrates the database forward; downgrading afterwards can corrupt it. Back up before upgrading.
Managed hosting
All managed plans get automatic daily snapshots kept about 14 days; the Community plan additionally gets hourly snapshots covering the last 24 hours. Backups are outage recovery, not an archive — destroyed or long-canceled servers cannot be recovered after backups age out. Restores are performed by support and roll the whole server back to the snapshot time: contact the support assistant with what happened and when.
Clustering
For large deployments, IPTinCan supports a primary-worker cluster architecture:
- Primary node — Handles database, authentication, and cluster coordination.
- Worker nodes — Handle client connections and voice routing, syncing state with the primary.
# Primary node config
[cluster]
enabled = true
role = "primary"
node_name = "primary-1"
cluster_port = 3787 # Inter-node TCP
cluster_udp_port = 3788 # Inter-node UDP voice relay
cluster_secret = "your-hmac-secret-here" # Min 16 characters
# Worker node config
[cluster]
enabled = true
role = "worker"
node_name = "worker-1"
cluster_port = 3787
cluster_udp_port = 3788
cluster_secret = "your-hmac-secret-here"
primary_address = "10.0.0.1"
primary_cluster_port = 3787
Worker nodes automatically synchronize their user roster, channel list, and permissions with the primary. The cluster uses HMAC authentication to verify inter-node communication. Voice packets are relayed between nodes over UDP port 3788.
Managed Hosting
On a paid plan we run the server for you: it lives at <name>.servers.iptincan.com with TLS, automatic backups, and direct support. All plans start with a 14-day free trial (except the $3/mo Licensed plan, which is for self-hosters).
After checkout
Your server is created automatically and is usually ready in 5–10 minutes. The confirmation page shows your server address, license key, and a default username + password — shown once, and also emailed to you. Lost them or never got the email? Contact support — we can resend them. If setup shows "Provisioning Issue", your payment is safe and setup retries automatically; if it hasn't recovered within ~30 minutes, contact support.
Billing & account self-service
Manage everything at iptincan.com/account — enter the email you purchased with, verify with a code, then use Manage billing (Stripe portal) to update cards, cancel, or view invoices. Dial-in phone numbers ($5/mo each; US, Canada, France, Netherlands, Finland, Denmark, Poland, Portugal) are also added and released there.
- Trial — 14 days; cancel before day 15 and there's no charge.
- Payment failure — you get an email and ~3 days to update your card; after that the server is suspended (paused, nothing deleted). Paying again brings it back automatically.
- Cancellation — the server runs until the end of the paid period, then it's shut down, the license is revoked, and the address and any phone numbers are released. Data is gone once backups age out (about 14 days).
- Status badges on the account page:
trialing,active,past_due(fix the card),canceling(runs until period end),canceled.
Server actions & status
Shut down, restart, and destroy are handled by support for now (there's no self-serve control panel yet) — ask the support assistant with your account email and server name. "Shut down" pauses the server with data kept; "Destroy" permanently deletes the server and its data. Live status of the platform and of your own server (by subdomain) is at status.iptincan.com.
Licensing
Self-hosting is free with unlimited users. A free license key ties your server to your email so it can validate, receive support, and stay part of the network — get one in seconds on the setup guide (no card required). Keys look like ITC-XXXX-XXXX-XXXX-XXXX.
[license]
key = "ITC-XXXX-XXXX-XXXX-XXXX"
server_url = "https://license.iptincan.com"
enforce = true
heartbeat_interval = 300
Restart the server after adding the key; it validates against license.iptincan.com on startup and checks in periodically.
What a paid license adds
The $3/mo Licensed plan (or any managed plan) additionally unlocks the free <name>.servers.iptincan.com subdomain with automatic dynamic DNS.
Good to know
- A license is bound to the first machine it runs on. Moving your server to new hardware? Contact support to unbind it first.
- Licensed servers keep working about 72 hours without internet, on their last successful check-in.
- All chat, voice, and video features work identically on the free key.
Admin Panel
The client includes a built-in admin panel for server administrators. Access it via the gear icon in the sidebar (visible only to users with admin privileges).
The admin panel includes eight tabs:
- Users — View all accounts, change roles, kick/ban users, reset passwords.
- Channels — Create, edit, and delete channels. Configure categories, permissions, and slow mode.
- Moderation — Review audit logs, manage warnings, configure auto-moderation keyword filters.
- Server Config — View server statistics, configure MOTD, manage server settings.
- Cluster — Monitor cluster node status, view connected worker nodes and their load.
- Access Tokens — Generate and manage API access tokens for programmatic server access.
- Approvals — Review and approve/deny pending user registration requests (when approval mode is enabled).
- VPN — Reserved for the VPN feature (in development).
Invites
There is no public signup anywhere in IPTinCan — people join your server only through an invite you mint under Admin → Invites: an ipt:// link or an ITC- code. Invites can expire or be revoked; "the server rejected this invite" means it's used up or stale — mint a fresh one. Recipients follow the Add a server connection guide.
Moderation
IPTinCan provides comprehensive moderation tools:
- Kick — Remove a user from the server. They can reconnect.
- Ban — Permanently block a user by account and/or IP address, with optional duration and reason.
- Timeout — Temporarily mute a user for a specified duration.
- Slow Mode — Limit message frequency per channel (e.g., one message every 5 seconds).
- Warnings — Issue formal warnings with notes. Warnings are tracked in the user's moderation history.
- Auto-Moderation — Configurable keyword filters that automatically delete messages and optionally timeout the sender.
- Audit Log — Every moderation action is logged with timestamp, moderator, target, and reason.
Access Tokens
Access tokens allow programmatic access to the server's REST API on port 3786. Admins can generate tokens from the Access Tokens tab in the admin panel. Tokens can be scoped and revoked at any time.
User Approval
When user approval mode is enabled, new account registrations are held in a pending state until an administrator approves them. This is useful for private communities that want to vet new members before granting access.
Pending registrations appear in the Approvals tab of the admin panel. Admins can approve or deny each request. Approved users receive access immediately; denied users are notified and their registration is discarded.
Client Guide
Connecting to a server
Open the IPTinCan app. On the connect screen, enter your server details:
hostname:port (e.g., chat.example.com:3784)
hostname (uses default port 3784)
IP address:port (e.g., 192.168.1.100:3784)
Or paste an invite from the server's admin — an ipt:// link (opens the app directly on most systems) or an ITC- code. To add another server while already connected to one, see Add a server connection. The app holds one active server at a time; joining a new one switches to it, and the current server stays saved to rejoin.
Authentication
You sign in with a username & password created on the server itself, or join via an invite link (ipt://) or invite code (ITC-…) from the server's admin. The server also has optional Google sign-in support, but that flow is not yet available in the current desktop app.
Chat features
- Markdown — Use
**bold**,*italic*,~~strikethrough~~, and`code`in messages. - Code blocks — Triple backticks with optional language for syntax highlighting.
- Reactions — React to messages with emojis.
- Replies — Quote and reply to any message.
- Direct messages — Send private messages to individual users.
- Search — Search across all messages (Ctrl/Cmd+K).
Video calls & screen sharing
Start a video call from any voice channel. Calls hold up to 8 participants with adaptive quality — "This call is full" means the limit is reached. Screen sharing is available with adjustable resolution and frame rate.
Common errors
- "Could not reach <host>:<port>" — check the server at status.iptincan.com (managed) or that it's running and port 3784 is open (self-hosted); then re-check the address and your network/firewall.
- "Couldn't auto-reconnect — its saved session may have expired" — harmless; rejoin the server from the list, or ask the admin for a fresh invite. No data is lost.
- "This server's license is suspended" — the server's subscription has a problem (usually payment). The server owner fixes it at iptincan.com/account; members should contact their admin.
- "LiveKit is not configured on this server" — self-hosted server without the call service; the admin should follow Voice & Video Calls.
Voice Settings
Calls run over LiveKit (WebRTC) using the Opus audio codec with adaptive quality.
Audio & video settings
- Input device — Select your microphone, with a live mic test meter.
- Output device — Select your speakers or headphones.
- Input gain — Amplify or reduce your microphone level (0–200%).
- Output volume — Master volume for all incoming audio.
- Echo cancellation — Toggle acoustic echo cancellation.
- Noise suppression — Toggle background-noise reduction.
- Camera & video quality — Pick a camera with live preview; set 360p/720p/1080p/Auto.
Push-to-talk and per-user volume are in development.
Camera or microphone won't start?
- On Windows, check Settings → Privacy & Security → Camera (and Microphone) and allow desktop apps.
- If the camera still fails, lower the video quality to 720p in Settings → Voice & Video — some cameras (e.g., the Razer Kiyo Pro) fail at 1080p. The app also retries with relaxed settings on its own.
- If no microphone is available, the app joins calls as a listener.
Ports & Protocols
| Port | Protocol | Service | Purpose |
|---|---|---|---|
3784 | TCP | itc-server | Text chat, control messages, authentication (desktop clients) |
3785 | UDP | itc-server | Media fallback |
3786 | TCP | itc-server | REST API and OAuth callbacks |
3789 | TCP | itc-server | WebSocket control plane (mobile clients) |
7880 | TCP | LiveKit | Call signaling (ws/wss) |
7881 | TCP | LiveKit | RTC over TCP fallback |
3478 | UDP | LiveKit | Embedded TURN relay |
50000–50100 | UDP | LiveKit | RTC media (bounded range) |
3787 | TCP | itc-server | Cluster inter-node TCP (optional) |
3788 | UDP | itc-server | Cluster inter-node UDP voice relay (optional) |
"Friends can't connect from outside my LAN" is almost always missing port-forwarding. Some ISPs (and most 4G/5G connections) use carrier-grade NAT, where port-forwarding alone isn't enough — LiveKit's embedded TURN relay covers calls, and a host with a real public IP (or a cheap VPS) covers the rest.
In Development
These are on the roadmap but not yet available — no dates promised. Track progress (and vote on what we build next) on the public roadmap.
- macOS, iOS, and Android apps
- File & photo sharing, message threads, link previews, custom emojis, custom status
- Built-in VPN (server-side config exists; apps can't enable it yet)
- Two-factor authentication and Steam/Xbox/Google sign-in
- Public server discovery browser
- Push-to-talk and per-user volume
- Public Docker image and Windows server build
FAQ
ipt:// link or an ITC- code, minted in their app under Admin → Invites. Paste it on the app's connect screen, or follow the Add a server connection guide if you're already on another server. If the invite is rejected, it expired or was used — ask for a fresh one.itc-server.db (plus its -shm/-wal sidecars), the recordings/ folder, and server.toml regularly — see Backups & Restore. Managed hosting includes automatic daily snapshots (kept ~14 days; Community also gets hourly snapshots for the last 24 hours) — contact support for a restore.