> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tell.rs/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-hosting

> Deploy Tell on your own Linux server with systemd.

Run Tell on your own infrastructure. One binary, no containers. Data never leaves your servers.

<Tabs>
  <Tab title="Install">
    <Steps>
      <Step title="Install">
        ```bash theme={null}
        curl -sSfL https://tell.rs | bash
        cp ~/.local/bin/tell /usr/local/bin/tell
        ```
      </Step>

      <Step title="Configure">
        Generate a config file and move it to a dedicated location:

        ```bash theme={null}
        tell init
        mkdir -p /etc/tell
        mv tell-config.toml /etc/tell/config.toml
        ```

        Edit `/etc/tell/config.toml` — set `data_dir` to `/opt/tell` and configure your pipeline:

        ```toml theme={null}
        data_dir = "/opt/tell"
        ```
      </Step>

      <Step title="Set up ClickHouse">
        Tell uses ClickHouse as the default analytics backend. Install it, start the server, and create the Tell tables:

        ```bash theme={null}
        curl https://clickhouse.com/ | sh
        ./clickhouse server &
        ```

        `tell init` generated a `setup.sql` file alongside the config. Run it to create the database and tables:

        ```bash theme={null}
        clickhouse-client < setup.sql
        ```

        <Note>This assumes ClickHouse is running with default settings. See [clickhouse.com](https://clickhouse.com/docs) for installation and configuration details.</Note>
      </Step>

      <Step title="Create a service user">
        ```bash theme={null}
        useradd -r -s /bin/false tell
        mkdir -p /opt/tell
        chown tell:tell /opt/tell
        chown tell:tell /etc/tell/config.toml
        chmod 600 /etc/tell/config.toml
        ```
      </Step>

      <Step title="Create the systemd unit">
        ```bash theme={null}
        echo '[Unit]
        Description=Tell
        After=network.target

        [Service]
        Type=simple
        User=tell
        Group=tell
        Environment=TELL_CONFIG=/etc/tell/config.toml
        ExecStart=/usr/local/bin/tell run
        Restart=always
        RestartSec=5
        WorkingDirectory=/opt/tell

        NoNewPrivileges=yes
        PrivateTmp=yes
        ProtectSystem=strict
        ProtectHome=yes
        ReadWritePaths=/opt/tell

        [Install]
        WantedBy=multi-user.target' > /etc/systemd/system/tell.service
        ```
      </Step>

      <Step title="Start and verify">
        ```bash theme={null}
        systemctl daemon-reload
        systemctl enable --now tell
        systemctl status tell
        ```

        Tell is running. By default, HTTP ingestion listens on port **8080** and TCP on **50000**. Point your SDKs to `your-server:8080`, or put Caddy in front to serve on 443.
      </Step>
    </Steps>

    <Check>Tell is installed and running. To start collecting data, head to the [Quickstart](/getting-started/quickstart).</Check>

    <Note>Set `TELL_CONFIG` in your shell so CLI commands (`tell plugin`, `tell tail`, `tell query`, etc.) pick up the right config and data directory.</Note>

    <CodeGroup>
      ```bash Bash theme={null}
      echo 'export TELL_CONFIG=/etc/tell/config.toml' >> ~/.bashrc
      source ~/.bashrc
      ```

      ```bash Fish theme={null}
      set -Ux TELL_CONFIG /etc/tell/config.toml
      ```

      ```bash Zsh theme={null}
      echo 'export TELL_CONFIG=/etc/tell/config.toml' >> ~/.zshrc
      source ~/.zshrc
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Update">
    ```bash theme={null}
    curl -sSfL https://tell.rs | bash
    cp ~/.local/bin/tell /usr/local/bin/tell
    systemctl restart tell
    ```
  </Tab>
</Tabs>

***

## Optional: TLS with Caddy

If you're exposing the Tell API or dashboard publicly, put a reverse proxy in front of it:

```bash theme={null}
apt install -y caddy
```

```bash theme={null}
echo 'tell.example.com {
    reverse_proxy localhost:3000
}' > /etc/caddy/Caddyfile

systemctl restart caddy
```

Caddy handles TLS certificates automatically via Let's Encrypt. Point your DNS A record to the server IP.
