# Infrastructure ## Overview - Source and CI: Gitea repository with Gitea Actions. - Build, deploy, run: local Dokploy instance. - Runtime: one bot container in long polling mode plus PostgreSQL. - The bot makes outbound HTTPS requests only. It exposes no ports. - Production deploys are manual only. Agents must not deploy, run production migrations, or change Dokploy settings. A human triggers every production deploy from Dokploy after CI passes; Dokploy pulls the commit from the Gitea integration. ```text Gitea push | v Gitea Actions: gofmt, vet, test, build | v Dokploy: build Dockerfile, inject env, run bot + postgres ``` ## Runtime ```text +---------+ +-------------+ | bot | -----> | postgres | +---------+ +-------------+ outbound HTTPS to Telegram ``` One bot instance. Long polling permits one consumer per bot token; do not scale the service to more than one replica. ## Configuration Dokploy injects these into the bot container: | Variable | Required | Purpose | | --- | --- | --- | | `TELEGRAM_BOT_TOKEN` | yes | Bot token from BotFather | | `BOT_OWNER_ID` | yes | Numeric Telegram user ID of the bot owner | | `DATABASE_URL` | yes | `postgres://user:pass@host:5432/db?sslmode=disable` | | `AUTO_MIGRATE` | no | Run GORM AutoMigrate at startup; default `true` | | `POSTGRES_USER` | compose | Database role for local Compose | | `POSTGRES_PASSWORD` | compose | Database password for local Compose | | `POSTGRES_DB` | compose | Database name for local Compose | For local development, copy `.env.example` to `.env` and fill it with throwaway credentials. That `.env` is safe to use at any time: it points at the local throwaway database and a development bot token, never production. Agents may run the local stack freely. Never commit `.env`. Production secrets exist only in Dokploy environment variables and must never be copied into `.env`. ## Local development ```sh cp .env.example .env docker compose up -d postgres make build make run ``` Or run the full stack: ```sh docker compose up --build ``` Use a separate bot token for development. ## Image `dockerfile` is a multi-stage build: compile a static binary, then run it on Alpine as an unprivileged `app` user. It keeps `ca-certificates` installed because the bot calls the Telegram API over TLS. ```sh docker build -t pllist-bot . ``` ## Gitea Actions CI runs on every push and pull request: ```yaml # .gitea/workflows/ci.yml name: ci on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: "1.27" - run: test -z "$(gofmt -l .)" - run: go vet ./... - run: go test ./... - run: go build ./... ``` ## Dokploy deploy 1. Open the local Dokploy instance and create a project named `pllist`. 2. Add a PostgreSQL service. Note its internal host, port, database, user, and password. 3. Add an application connected to the Gitea repository. 4. Select the Dockerfile build type and set the build context to the repository root. 5. Set `TELEGRAM_BOT_TOKEN`, `BOT_OWNER_ID`, and `DATABASE_URL` in the application environment. Use the PostgreSQL service host from step 2. 6. Set replicas to `1`. Long polling does not support multiple replicas. 7. Deploy manually. Dokploy pulls the repository, builds the image, and starts the container. 8. Keep auto-deploy disabled. After CI passes, a human triggers Deploy in Dokploy. Agents never trigger it. Alternatively, deploy the repository as a Dokploy Compose service using `docker-compose.yml`. This runs both the bot and PostgreSQL in one stack. Compose creates the `bot-net` network itself; it must not be declared `external` unless it is created separately in advance. Check logs in Dokploy after deploy. A successful start shows the bot polling Telegram with no errors. If the process exits, the most common causes are a missing environment variable, a wrong `DATABASE_URL`, or a bad bot token. ## Operations - Restart the application from Dokploy after changing environment variables. - Rebuild and redeploy after a new image is needed. - Back up PostgreSQL with `pg_dump` before destructive changes. - Keep the bot token and database password only in Dokploy environment variables.