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

# Docker Installation

> Install Wirekite as a Docker container on a Linux host.

The Docker path ships the same install tree baked into a single runtime image.
You pull the image from Docker Hub (or load it from a tarball for air-gapped
hosts), then run a small wrapper script that renders configuration, stages your
license, mints a TLS cert, and starts the container.

## Requirements

| Requirement      | Notes                                                                          |
| ---------------- | ------------------------------------------------------------------------------ |
| Operating system | Any Linux distro that runs current Docker                                      |
| Docker engine    | 20.10 or newer (`docker --version`)                                            |
| Privileges       | Root or `sudo` (the wrapper writes under `/var/lib/wirekite/`)                 |
| Free TCP port    | `8443` by default (changeable via `--port-host`)                               |
| Outbound HTTPS   | To `docker.io` for the image pull, and to your target databases for migrations |
| Disk             | \~700 MB for the image; migration data + change files on disks you allocate    |

## What you receive from Wirekite

Three things, delivered out-of-band:

1. **Docker Hub credentials** — a username + Personal Access Token (PAT) that
   grants read access to `wirekite/wirekite`. (Air-gapped customers receive a
   `wirekite-image.tar` instead.)
2. **License pair** — `wirekite.license` and `wirekite.key`. Keep both files
   together.
3. **A pinned image tag** — for example `wirekite/wirekite:0.1.0`. The same
   image supports every source and target Wirekite ships.

### Stage the license

Place both license files in a single directory on the host. The path is your
choice; you'll pass it to `--license-pair-dir` later.

```bash theme={null}
sudo mkdir -p /opt/wirekite/license
sudo cp wirekite.license wirekite.key /opt/wirekite/license/
sudo chmod 0644 /opt/wirekite/license/wirekite.{license,key}
```

Both files must be readable by the container's `wirekite` user (uid `999`);
mode `0644` covers that.

## One-time setup

### Docker login

```bash theme={null}
docker login -u <your-issued-username> docker.io
# Password: paste the PAT you received.
```

A warning about unencrypted credential storage is normal on a server without
Docker Desktop; configure a system credential helper later if your security
policy requires it.

### (Optional) Provision data + change disks

For production, allocate two host directories — one for each migration's
**data** files (initial-load rows in transit) and one for **change** files
(CDC chunks). They can sit on separate physical disks for better throughput.

```bash theme={null}
# Substitute your block devices
sudo mkfs.ext4 /dev/sdb
sudo mkfs.ext4 /dev/sdc

sudo mkdir -p /mnt/wk-data /mnt/wk-change
sudo mount /dev/sdb /mnt/wk-data
sudo mount /dev/sdc /mnt/wk-change

echo "/dev/sdb /mnt/wk-data   ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab
echo "/dev/sdc /mnt/wk-change ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab

# Allow the container's wirekite uid (999) to read/write
sudo chown 999:999 /mnt/wk-data /mnt/wk-change
```

Sizing rule of thumb: data disk ≈ 2× the largest single-pass extract;
change disk ≈ 24 hours of CDC throughput. Most customers start with
100 GB data + 50 GB change.

If you skip this section, Wirekite falls back to a single directory under
`/var/lib/wirekite/<your-id>/data/` — fine for evaluation, not recommended
for production.

## Install in three steps

### Step 1: Extract the wrapper script from the image

```bash theme={null}
docker run --rm --entrypoint=cat \
    wirekite/wirekite:<tag> /opt/wirekite/scripts/docker_setup.sh \
    > docker_setup.sh && chmod +x docker_setup.sh
```

This implicitly pulls the image (\~700 MB first time) and writes
`docker_setup.sh` to your current directory. Substitute `<tag>` with the
pinned tag you received.

### Step 2: Run the wrapper

Pick **one** invocation depending on whether you provisioned split disks.

**Single-mount (evaluation / dev):**

```bash theme={null}
sudo ./docker_setup.sh customer <your-id> \
    --public-hostname=<host-or-ip> \
    --license-pair-dir=/opt/wirekite/license \
    --image-tag=wirekite/wirekite:<tag>
```

**Split-disk (production-recommended):**

```bash theme={null}
sudo ./docker_setup.sh customer <your-id> \
    --public-hostname=<host-or-ip> \
    --license-pair-dir=/opt/wirekite/license \
    --image-tag=wirekite/wirekite:<tag> \
    --data-disk=/mnt/wk-data \
    --change-disk=/mnt/wk-change
```

Where:

* `<your-id>` — a short identifier you pick (lowercase alphanumeric + hyphens).
  Becomes the container name (`wirekite-<your-id>`) and the per-customer state
  dir (`/var/lib/wirekite/<your-id>/` by default).
* `<host-or-ip>` — the hostname or IP your users will type in a browser. This
  value is baked into the TLS certificate's SAN so the browser doesn't flag a
  mismatch.

<Note>
  **TLS and Let's Encrypt**: by default Wirekite mints a self-signed CA.
  Browsers will show a warning until users accept the cert or you bring your own.
  Let's Encrypt **does not issue certificates for IPs** — it requires a real DNS
  name. To use a CA-issued cert see [Bring your own TLS
  certificate](#bring-your-own-tls-certificate) below.
</Note>

On success the wrapper prints:

```
== Done — container 'wirekite-<your-id>' is up ==

  Customer URL : https://<host>:8443
```

### Step 3: Browse to the URL

Open `https://<host>:8443/` in a browser. Accept the self-signed cert warning
(or use a CA-issued cert as below). You'll land on the **setup page**. Create
the **root user** (username + password), then sign in.

## Bring your own TLS certificate

If your organization requires a CA-issued certificate, pass the cert flags
instead of relying on the default self-signed CA:

```bash theme={null}
sudo ./docker_setup.sh customer <your-id> \
    --public-hostname=<host-or-ip> \
    --license-pair-dir=/opt/wirekite/license \
    --image-tag=wirekite/wirekite:<tag> \
    --cert-mode=customer \
    --cert-file=/path/to/your/server.crt \
    --key-file=/path/to/your/server.key \
    [--chain-file=/path/to/intermediate-chain.crt] \
    [--data-disk=/mnt/wk-data --change-disk=/mnt/wk-change]
```

The cert + key files are copied into the container's state dir and bind-mounted
read-only. The certificate's `CN` or SAN must include `<host-or-ip>`.

Wirekite does **not** run ACME or auto-renew certs inside the container — that
is your operational responsibility.

## Common operations

### Restart the container

```bash theme={null}
docker restart wirekite-<your-id>
```

State on the named volumes is preserved; in-flight migrations reattach
automatically.

### Upgrade to a new image tag

```bash theme={null}
docker rm -f wirekite-<your-id>
# Re-run the same docker_setup.sh customer ... command with --image-tag=<new-tag>
```

Persistent state (encryption key, certs, license, migration history) survives
the recreate because it lives on named volumes and host bind-mounts, not on
the container's writable layer.

### Stop temporarily

```bash theme={null}
docker stop wirekite-<your-id>
docker start wirekite-<your-id>
```

Auto-restart on host reboot is on by default (`--restart=unless-stopped`).

### Uninstall

```bash theme={null}
docker rm -f wirekite-<your-id>
docker volume rm wirekite-<your-id>-instance wirekite-<your-id>-certs
sudo rm -rf /var/lib/wirekite/<your-id>
docker rmi wirekite/wirekite:<tag>
```

Migration data on bind-mounted disks (`/mnt/wk-data`, `/mnt/wk-change`) is
preserved unless you remove those host directories yourself.

## Troubleshooting

### `docker pull` fails with "denied: requested access to the resource is denied"

You're not logged in or your PAT lacks read access to `wirekite/wirekite`. Run
`docker login -u <your-username> docker.io` and paste your PAT.

### Wrapper says "container 'wirekite-`<id>`' already exists"

A previous install left a stopped or running container. Remove it:

```bash theme={null}
docker rm -f wirekite-<your-id>
```

Then re-run the wrapper.

### `docker logs` shows "license file does not exist"

The `--license-pair-dir` you passed doesn't contain `wirekite.license` and
`wirekite.key`, or the directory permissions block the container's uid (999).

```bash theme={null}
ls -la <license-pair-dir>/wirekite.license <license-pair-dir>/wirekite.key
# Both files should be readable; mode 0644 is fine
```

### Container restarts in a loop

```bash theme={null}
docker logs --tail 50 wirekite-<your-id>
```

Common causes:

* License invalid or expired — contact your Wirekite rep
* Bind-mounted cert/key files unreadable — check permissions (`0644`)
* Port `8443` already in use on the host — stop the conflicting process or
  pass `--port-host=<other-port>` to the wrapper

### Cannot reach a database at `127.0.0.1` from the container

The container is on Docker's default bridge network — `127.0.0.1` inside the
container is the container's own loopback, not the host's. Use the host's
reachable IP, or ask your Wirekite rep about local-mode (host-network) installs
for same-host MySQL/Postgres source extracts.
