4.1 KiB
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.
Gitea push
|
v
Gitea Actions: gofmt, vet, test, build
|
v
Dokploy: build Dockerfile, inject env, run bot + postgres
Runtime
+---------+ +-------------+
| 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
cp .env.example .env
docker compose up -d postgres
make build
make run
Or run the full stack:
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.
docker build -t pllist-bot .
Gitea Actions
CI runs on every push and pull request:
# .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
- Open the local Dokploy instance and create a project named
pllist. - Add a PostgreSQL service. Note its internal host, port, database, user, and password.
- Add an application connected to the Gitea repository.
- Select the Dockerfile build type and set the build context to the repository root.
- Set
TELEGRAM_BOT_TOKEN,BOT_OWNER_ID, andDATABASE_URLin the application environment. Use the PostgreSQL service host from step 2. - Set replicas to
1. Long polling does not support multiple replicas. - Deploy manually. Dokploy pulls the repository, builds the image, and starts the container.
- 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.
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_dumpbefore destructive changes. - Keep the bot token and database password only in Dokploy environment variables.