# Deploying TikTok Manager to ttok.thinkera.academy

The production instance runs on the Thinkera server under
`/var/www/private/thinkera.academy/ttok.thinkera.academy`, listens on `127.0.0.1:9506`, and is
reached only through Apache over HTTPS at `https://ttok.thinkera.academy`.

## 1. DNS (GoDaddy, thinkera.academy)

| Type | Name | Value |
|------|------|-------|
| A | `ttok` | `168.119.214.202` |

Wait until `nslookup ttok.thinkera.academy 8.8.8.8` answers the server's address.

## 2. Copy the project

Copy everything **except** `.env`, `.venv/`, `data/`, `uploads/`, `media/`, `dev-certs/` and
`__pycache__/` folders. The server builds its own image and starts with an empty database.

## 3. The server's `.env`

Start from `.env.example` and set:

| Variable | Value on the server |
|----------|--------------------|
| `FLASK_ENV` | `production` |
| `PORT` | `9506` |
| `TIKTOK_REDIRECT_URI` | `https://ttok.thinkera.academy/auth/callback` |
| `TIKTOK_CLIENT_KEY` / `TIKTOK_CLIENT_SECRET` | the Sandbox keys until TikTok approves the app, then the Production keys |
| `TIKTOK_ALLOWED_ACCOUNTS` | the open_id / union_id values allowed to sign in (required: the app refuses to start when empty) |
| `SECRET_KEY` | new: `python3 -c "import secrets; print(secrets.token_hex(32))"` |
| `API_KEY` | new: `python3 -c "import secrets; print(secrets.token_hex(32))"` |
| `TOKEN_ENCRYPTION_KEY` | new: `python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"` |
| `SSL_CRT_FILE` / `SSL_KEY_FILE` | empty: Apache terminates TLS, the container speaks plain HTTP on loopback |

Never reuse the laptop's `SECRET_KEY`, `API_KEY` or `TOKEN_ENCRYPTION_KEY`.

**Finding an ID for the allowlist:** a TikTok account that is not on the list is refused at sign-in,
and the login page shows its ID. Add that ID to `TIKTOK_ALLOWED_ACCOUNTS` and run
`docker compose up -d`. The `union_id` is the same in the Sandbox and the Production app; the
`open_id` changes between them.

## 4. Start

```bash
cd /var/www/private/thinkera.academy/ttok.thinkera.academy
docker compose up -d --build
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9506/login     # 200
```

## 5. Apache + certificate

`/etc/apache2/sites-available/ttok.thinkera.academy.conf`:

```apache
<VirtualHost *:80>
    ServerName ttok.thinkera.academy
    ProxyPreserveHost On
    ProxyTimeout 600
    RequestHeader set X-Forwarded-Proto "https"
    ProxyPass        / http://127.0.0.1:9506/
    ProxyPassReverse / http://127.0.0.1:9506/
</VirtualHost>
```

```bash
a2ensite ttok.thinkera.academy
apache2ctl configtest          # Apache serves ~15 other sites: never reload on a failed test
systemctl reload apache2
certbot --apache -d ttok.thinkera.academy
```

`ProxyTimeout 600` covers large video uploads; gunicorn's own timeout is 300 s per request.

## 6. TikTok developer portal

Add `https://ttok.thinkera.academy/auth/callback` to Login Kit → Redirect URI (Web) in the Sandbox
and in Production. The domain `thinkera.academy` must be verified under **URL properties** (a DNS
TXT record per app/sandbox).

## 7. Check

1. `https://ttok.thinkera.academy` shows "Continue with TikTok".
2. Sign in with an allowed account → Dashboard with followers, likes and video counts.
3. Sign in with an account that is not listed → refused, with its ID shown.
4. `docker logs tiktok-manager` shows no exception text and no token.
