Skip to main content

Standalone Daemon Administration

This guide covers managing clients, IP assignments, and connection profiles when running the Camouflage daemon in standalone mode (without the Enterprise backend).

Overview

In standalone mode, the daemon (camouflage-daemon) manages its own client registry via a clients.toml file. Every client must have a registered auth key to connect, and each client receives a fixed IP address that persists across reconnections.

The daemon provides four management subcommands:

CommandPurpose
camouflage-daemon add-clientRegister a new client and assign a fixed IP
camouflage-daemon revoke-clientDisable a client's access
camouflage-daemon list-clientsShow all registered clients
camouflage-daemon export-profileGenerate a .camouflage connection profile

Client Registry (clients.toml)

The client registry is stored alongside your daemon config. If your config is at /etc/camouflage/config.toml, the registry will be at /etc/camouflage/clients.toml.

File Format

[settings]
ttl_days = 30
subnet = "10.99.0.0/24"

[clients.tskey-abc123...]
ip = "10.99.0.2"
name = "alice-laptop"
enabled = true
last_seen = "2025-02-12T10:30:00Z"

[clients.tskey-def456...]
ip = "10.99.0.3"
name = "bob-desktop"
enabled = true

Settings

FieldDefaultDescription
ttl_days30Unused client expiration (future use)
subnet10.99.0.0/24Subnet for IP allocation. Must match daemon config.

Client Fields

FieldDescription
ipFixed IPv4 address assigned to this client
nameHuman-readable name for identification
enabledtrue to allow connections, false to revoke
last_seenISO 8601 timestamp of last connection (auto-updated)

Adding Clients

Register a new client with add-client:

# Basic usage - name is required
camouflage-daemon add-client --name "alice-laptop"

# Output:
# Client added successfully
# Name: alice-laptop
# Auth Key: tskey-a1b2c3d4e5f6...
# IP: 10.99.0.2
#
# Save the auth key - it cannot be recovered later.

# Assign a specific IP address
camouflage-daemon add-client --name "server-node" --ip 10.99.0.100

Options

FlagDescription
--name <NAME>Required. Human-readable client name
--ip <IP>Optional. Assign a specific IP instead of auto-assigning
--config <PATH>Path to daemon config (default: /etc/camouflage/config.toml)

Auth Key Format

Auth keys follow the format tskey-{64_hex_chars} (70 characters total). They are generated using cryptographically secure random bytes and cannot be recovered after creation.

Revoking Clients

Disable a client's access with revoke-client:

camouflage-daemon revoke-client --auth-key "tskey-a1b2c3d4e5f6..."

# Output:
# Client 'alice-laptop' has been revoked.

Revoking sets enabled = false in clients.toml. The client's IP reservation is kept so it can be re-enabled later if needed. Active connections from the revoked client will be rejected on next reconnect.

Listing Clients

View all registered clients:

camouflage-daemon list-clients

# Output:
# Clients (2 registered):
# tskey-a1b2... alice-laptop 10.99.0.2 enabled last seen: 2025-02-12T10:30:00Z
# tskey-d4e5... bob-desktop 10.99.0.3 revoked last seen: 2025-02-11T08:15:00Z

Exporting Connection Profiles

Generate a .camouflage profile file that clients can import to connect:

# Export to stdout
camouflage-daemon export-profile \
--auth-key "tskey-a1b2c3d4e5f6..." \
--server "vpn.example.com:61700"

# Export to file
camouflage-daemon export-profile \
--auth-key "tskey-a1b2c3d4e5f6..." \
--server "vpn.example.com:61700" \
--output alice-laptop.camouflage

# With custom KEX method
camouflage-daemon export-profile \
--auth-key "tskey-a1b2c3d4e5f6..." \
--server "vpn.example.com:61700" \
--kex hybrid

Options

FlagDescription
--auth-key <KEY>Required. The client's auth key
--server <HOST:PORT>Required. Daemon address clients will connect to
--kex <METHOD>Key exchange method: hybrid (default), pqxdh, or noise
--output <PATH>Write to file instead of stdout

Profile Format

The exported .camouflage file is a JSON document compatible with the Camouflage desktop app and CLI client:

{
"version": "1.0",
"type": "camouflage-connection",
"connection": {
"id": "a1b2c3d4-e5f6-...",
"name": "alice-laptop",
"server": "vpn.example.com:61700",
"auth_key": "tskey-a1b2c3d4e5f6...",
"kex": "hybrid",
"network_name": "",
"route_all_traffic": false,
"is_relay": true,
"created_at": "2025-02-12T10:30:00Z"
}
}

Importing Profiles (Client Side)

Clients can import a .camouflage profile to connect:

CLI Client

# Connect using a profile file
camouflage-client connect --profile alice-laptop.camouflage

The --profile flag reads the server address, auth key, KEX method, and other settings from the profile file. It overrides any --server, --auth-key, or --kex flags.

Desktop App

  1. Open Camouflage desktop app
  2. Click "Import Profile" or drag-and-drop the .camouflage file
  3. The connection will appear in your connection list

Fixed IP Assignment

Every registered client receives a fixed IP address from the daemon's subnet. This address is persistent:

  • Same IP on every reconnect — the client always gets the same address
  • Reserved while disconnected — the IP is not reassigned to other clients
  • Survives daemon restarts — stored in clients.toml on disk

How It Works

  1. When you add-client, the next available IP in the subnet is assigned (skipping .0, .1, and .255)
  2. When a client connects, the daemon looks up their auth key and assigns their registered IP
  3. When a client disconnects, the IP is released from the active pool but stays reserved in clients.toml
  4. On the next connection with the same auth key, the same IP is allocated again

Enterprise Mode

When the daemon is connected to the Camouflage Enterprise backend, IP assignments are managed centrally via the API. The daemon queries the backend's /daemon/node-ip/ endpoint with the client's auth key and receives the assigned IP. If the API is unreachable, the daemon falls back to clients.toml.

Authentication Flow

The daemon enforces auth key validation on every connection:

Client connects with auth_key
├─ No auth_key provided → Connection REJECTED
└─ auth_key provided →
Enterprise backend configured?
├─ YES → Query backend API for IP
│ ├─ 200 OK → Assign fixed IP, allow connection
│ ├─ 403 Forbidden → Connection REJECTED (client disabled)
│ ├─ 404 Not Found → Connection REJECTED (unknown client)
│ └─ Timeout → Fall back to clients.toml lookup
└─ NO → Look up auth_key in clients.toml
├─ Found + enabled → Assign fixed IP, allow connection
└─ Not found or disabled → Connection REJECTED

Typical Workflow

1. Set up the daemon

# Generate daemon config
camouflage-daemon --generate-config
# Edit /etc/camouflage/config.toml as needed

2. Register clients

camouflage-daemon add-client --name "alice-laptop"
camouflage-daemon add-client --name "bob-desktop"
camouflage-daemon add-client --name "server-01" --ip 10.99.0.100

3. Export and distribute profiles

camouflage-daemon export-profile \
--auth-key "tskey-..." \
--server "vpn.example.com:61700" \
--output alice-laptop.camouflage

Send the .camouflage file to the user via a secure channel.

4. Start the services

# Enable and start both the VPN daemon and client daemon
sudo systemctl enable --now camouflage camouflage-client

# Verify they're running
sudo systemctl status camouflage camouflage-client

# View logs
journalctl -u camouflage -f
journalctl -u camouflage-client -f

5. Clients connect

camouflage-client connect --profile alice-laptop.camouflage

6. Monitor and manage

# Check who's registered
camouflage-daemon list-clients

# Revoke access
camouflage-daemon revoke-client --auth-key "tskey-..."