├── DUMMY.txt ├── img ├── screen-001.png └── screen-002.png ├── Dockerfile ├── .github └── workflows │ ├── keep_active.yml │ └── build_image.yml ├── LICENSE └── README.md /DUMMY.txt: -------------------------------------------------------------------------------- 1 | This is a dummy file to keep the repository active. 2 | -------------------------------------------------------------------------------- /img/screen-001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukaszraczylo/tdlib-telegram-bot-api-docker/HEAD/img/screen-001.png -------------------------------------------------------------------------------- /img/screen-002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukaszraczylo/tdlib-telegram-bot-api-docker/HEAD/img/screen-002.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest as buildBase 2 | RUN apk add --no-cache alpine-sdk linux-headers git zlib-dev openssl-dev gperf php cmake ccache 3 | ADD . /srv 4 | WORKDIR /srv 5 | RUN --mount=type=cache,target=/root/.cache/git \ 6 | git submodule update --init --recursive 7 | RUN mkdir -p build && cd build && \ 8 | cmake -DCMAKE_INSTALL_PREFIX:PATH=../tdlib -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. 9 | RUN --mount=type=cache,target=/root/.ccache \ 10 | cd /srv/build && \ 11 | export CCACHE_DIR=/root/.ccache && \ 12 | cmake --build . --target install -j$(nproc) 13 | # RUN upx --best /srv/build/telegram-bot-api 14 | 15 | FROM alpine:latest 16 | RUN apk add --no-cache zlib-dev openssl-dev libstdc++ 17 | COPY --from=buildBase /srv/build/telegram-bot-api /srv/telegram-bot-api 18 | VOLUME /data 19 | ENTRYPOINT ["/srv/telegram-bot-api", "--dir=/data"] 20 | -------------------------------------------------------------------------------- /.github/workflows/keep_active.yml: -------------------------------------------------------------------------------- 1 | name: Keep Repository Active 2 | 3 | on: 4 | schedule: 5 | # Runs at 00:00 UTC every Monday 6 | - cron: '0 0 * * 1' 7 | 8 | # Allow manual trigger for testing 9 | workflow_dispatch: 10 | 11 | jobs: 12 | update-dummy: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | 19 | - name: Modify dummy file 20 | run: | 21 | if grep -q " $" DUMMY.txt; then 22 | # If file ends with space, remove it 23 | sed -i 's/ $//' DUMMY.txt 24 | else 25 | # If file doesn't end with space, add one 26 | echo -n " " >> DUMMY.txt 27 | fi 28 | 29 | - name: Commit and push if changed 30 | run: | 31 | git config --global user.name 'GitHub Action' 32 | git config --global user.email 'action@github.com' 33 | git add DUMMY.txt 34 | git diff --quiet && git diff --staged --quiet || (git commit -m "Update DUMMY.txt to keep repository active" && git push) 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Lukasz Raczylo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tdlib-telegram-bot-api-docker 2 | 3 | ## Purpose of the project 4 | 5 | Produce working, minimal Docker image for the Telegram Bot API server together with easy 6 | to use pipeline generating builds on the changes within the main repository managed by 7 | Telegram team. 8 | 9 | **Motivation:** [#0](https://medium.com/swlh/building-your-home-raspberry-pi-kubernetes-cluster-14eeeb3c521e), [#1](https://github.com/tdlib/telegram-bot-api/issues/65), [#2](https://github.com/tdlib/telegram-bot-api/issues/65) 10 | 11 | This project does not modify any part of the [tdlib/telegram-bot-api](https://github.com/tdlib/telegram-bot-api) code. 12 | 13 | ## Issues 14 | 15 | As I do not modify any part of the server code I am not responsible for the way it works. For that purpose you should open an issue on the [telegram bot api server](https://github.com/tdlib/telegram-bot-api/issues) issue tracker. 16 | 17 | **TL;DR:** My responsibility ends when container and binary starts. 18 | 19 | ## Build schedule 20 | Build will be triggered automatically once a week to produce the latest version of the Telegram API Server. 21 | I would set it for the daily release but every build takes ~2.5 hours and generates additional costs on my side. 22 | 23 | Images are versioned in format `1.0.x` where `x` is a build number. 24 | There's additional version tag added, for example `api-5.1` where `5.1` is the version of Telegram API supported by the image. 25 | 26 | ## How to use the image 27 | 28 | Images created within this project support following architectures: AMD64 and ARM64 29 | 30 | Yes, it means you can run them on regular servers and **Raspberry Pi 4** and above as well! 🥳 31 | 32 | ### Github authentication 33 | 34 | ~~You may need to authenticate with github ([see this thread](https://github.community/t/docker-pull-from-public-github-package-registry-fail-with-no-basic-auth-credentials-error/16358/87)) to pull even the publicly available images. To do so you need to create [Personal Access Token](https://github.com/settings/tokens/new) with `read:packages` scope and use it to authenticate your docker client with the Github Docker Registry.~~ 35 | 36 | Update: After move to GHCR.io there's no need authenticate and you should be able to pull images without any additional magic. 37 | 38 | ### Docker configuration 39 | 40 | ``` 41 | docker pull ghcr.io/lukaszraczylo/tdlib-telegram-bot-api-docker/telegram-api-server:latest 42 | docker run -p 8081:8081 -e TELEGRAM_API_ID=yourApiID -e TELEGRAM_API_HASH=yourApiHash -t ghcr.io/lukaszraczylo/tdlib-telegram-bot-api-docker/telegram-api-server 43 | ``` 44 | 45 | *Thing to remember:* Entrypoint is set to the server binary, therefore you can still modify parameters on the go, as shown below 46 | 47 | #### Setting the log output and verbosity 48 | ![Set the log output and verbosity](img/screen-001.png?raw=true) 49 | 50 | #### Printing out the help 51 | ![Print out the help](img/screen-002.png?raw=true) 52 | 53 | ### Kubernetes configuration 54 | 55 | Example deployment within kubernetes cluster 56 | 57 | ```yaml 58 | # apiVersion: v1 59 | # kind: PersistentVolumeClaim 60 | # metadata: 61 | # name: telegram-api 62 | # spec: 63 | # accessModes: 64 | # - ReadWriteMany 65 | # storageClassName: longhorn 66 | # resources: 67 | # requests: 68 | # storage: 5Gi 69 | 70 | --- 71 | apiVersion: apps/v1 72 | kind: Deployment 73 | metadata: 74 | name: telegram-api 75 | labels: 76 | app: telegram-api 77 | spec: 78 | selector: 79 | matchLabels: 80 | app: telegram-api 81 | replicas: 2 82 | template: 83 | metadata: 84 | labels: 85 | app: telegram-api 86 | spec: 87 | containers: 88 | - name: bot-api 89 | image: ghcr.io/lukaszraczylo/tdlib-telegram-bot-api-docker/telegram-api-server:latest 90 | imagePullPolicy: Always 91 | args: [ "--local", "--max-webhook-connections", "1000" ] 92 | resources: 93 | requests: 94 | cpu: 100m 95 | memory: 100Mi 96 | limits: 97 | cpu: 500m 98 | memory: 500Mi 99 | ports: 100 | - containerPort: 8081 101 | protocol: TCP 102 | name: api 103 | env: 104 | - name: TELEGRAM_API_ID 105 | value: "xxx" 106 | - name: TELEGRAM_API_HASH 107 | value: "yyy" 108 | # volumeMounts: 109 | # - name: shared-storage 110 | # mountPath: /data 111 | # volumes: 112 | # - name: shared-storage 113 | # persistentVolumeClaim: 114 | # claimName: telegram-api 115 | affinity: 116 | nodeAffinity: 117 | requiredDuringSchedulingIgnoredDuringExecution: 118 | nodeSelectorTerms: 119 | - matchExpressions: 120 | - key: node-role.kubernetes.io/control-plane 121 | operator: DoesNotExist 122 | - key: node-role.kubernetes.io/storage 123 | operator: DoesNotExist 124 | - key: node-role.kubernetes.io/highmem 125 | operator: Exists 126 | ``` 127 | -------------------------------------------------------------------------------- /.github/workflows/build_image.yml: -------------------------------------------------------------------------------- 1 | name: Build Telegram API server 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: "0 2 */7 * *" 6 | jobs: 7 | build: 8 | runs-on: ubuntu-24.04 9 | strategy: 10 | matrix: 11 | platform: 12 | - linux/amd64 13 | - linux/arm64 14 | name: Build ${{ matrix.platform }} image 15 | steps: 16 | - name: Checkout API repo 17 | uses: actions/checkout@v4 18 | with: 19 | repository: 'tdlib/telegram-bot-api' 20 | path: '/home/runner/work/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api' 21 | - name: Checkout Dockerfile 22 | uses: actions/checkout@v4 23 | with: 24 | repository: 'lukaszraczylo/tdlib-telegram-bot-api-docker' 25 | path: '/home/runner/work/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api-docker/docker' 26 | - name: Apply Dockerfile 27 | run: | 28 | cp /home/runner/work/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api-docker/docker/Dockerfile /home/runner/work/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api/Dockerfile 29 | - name: Get release sha and run number 30 | id: get_sha 31 | run: | 32 | echo "GITHUB_SHA=$(echo ${GITHUB_SHA::8})" >> $GITHUB_ENV 33 | echo "GITHUB_RUN_ID=$(echo ${GITHUB_RUN_NUMBER})" >> $GITHUB_ENV 34 | - name: Set up QEMU 35 | uses: docker/setup-qemu-action@v3 36 | - name: Set up Docker Buildx 37 | id: buildx 38 | uses: docker/setup-buildx-action@v3 39 | - name: Login to GHCR 40 | if: github.event_name != 'pull_request' 41 | uses: docker/login-action@v3 42 | with: 43 | registry: ghcr.io 44 | username: ${{ github.actor }} 45 | password: ${{ secrets.GCHR_PAT }} 46 | - name: Prepare for push 47 | id: prep 48 | run: | 49 | DOCKER_IMAGE=ghcr.io/${{ github.repository_owner }}/tdlib-telegram-bot-api-docker/telegram-api-server 50 | VERSION=edge 51 | if [[ $GITHUB_REF == refs/tags/* ]]; then 52 | VERSION=${GITHUB_REF#refs/tags/v} 53 | fi 54 | if [ "${{ github.event_name }}" = "schedule" ]; then 55 | VERSION=nightly 56 | fi 57 | # Platform-specific tag for this build job 58 | PLATFORM_TAG=$(echo ${{ matrix.platform }} | sed 's/\//-/g') 59 | TAGS="${DOCKER_IMAGE}:${VERSION}-${PLATFORM_TAG}" 60 | TAGS="$TAGS,${DOCKER_IMAGE}:${{ env.GITHUB_SHA }}-${PLATFORM_TAG}" 61 | 62 | TG_API_VERSION=$(grep "project(TelegramBotApi" /home/runner/work/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api/CMakeLists.txt | awk '{print $3}') 63 | echo "tags=${TAGS}" >> $GITHUB_OUTPUT 64 | echo "version=${VERSION}" >> $GITHUB_OUTPUT 65 | echo "tg_api_version=${TG_API_VERSION}" >> $GITHUB_OUTPUT 66 | echo "image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT 67 | # lowercase the branch name 68 | BRANCH=$(echo ${GITHUB_REF##*/} | tr '[A-Z]' '[a-z]') 69 | LABELS="org.opencontainers.image.revision=$GITHUB_SHA" 70 | LABELS="$LABELS,org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" 71 | LABELS="$LABELS,org.opencontainers.image.version=$VERSION" 72 | LABELS="$LABELS,com.github.repo.branch=$BRANCH" 73 | LABELS="$LABELS,com.github.repo.dockerfile=Dockerfile" 74 | echo "labels=${LABELS}" >> $GITHUB_OUTPUT 75 | BUILD_ARGS="BRANCH=$BRANCH" 76 | echo "args=${BUILD_ARGS}" >> $GITHUB_OUTPUT 77 | - name: Tag names 78 | run: echo ${{ steps.prep.outputs.tags }} 79 | - name: Build and push 80 | id: docker_build 81 | timeout-minutes: 350 82 | uses: docker/build-push-action@v6 83 | with: 84 | builder: ${{ steps.buildx.outputs.name }} 85 | context: /home/runner/work/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api 86 | file: /home/runner/work/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api-docker/tdlib-telegram-bot-api/Dockerfile 87 | platforms: ${{ matrix.platform }} 88 | push: ${{ github.event_name != 'pull_request' }} 89 | tags: ${{ steps.prep.outputs.tags }} 90 | build-args: ${{ steps.prep.outputs.args }} 91 | labels: ${{ steps.prep.outputs.labels }} 92 | cache-from: type=gha,scope=${{ matrix.platform }} 93 | cache-to: type=gha,mode=max,scope=${{ matrix.platform }} 94 | outputs: 95 | version: ${{ steps.prep.outputs.version }} 96 | tg_api_version: ${{ steps.prep.outputs.tg_api_version }} 97 | image: ${{ steps.prep.outputs.image }} 98 | 99 | create-manifest: 100 | needs: build 101 | runs-on: ubuntu-24.04 102 | if: github.event_name != 'pull_request' 103 | name: Create multi-arch manifest 104 | steps: 105 | - name: Set up Docker Buildx 106 | uses: docker/setup-buildx-action@v3 107 | - name: Login to GHCR 108 | uses: docker/login-action@v3 109 | with: 110 | registry: ghcr.io 111 | username: ${{ github.actor }} 112 | password: ${{ secrets.GCHR_PAT }} 113 | - name: Get build outputs 114 | id: outputs 115 | run: | 116 | echo "VERSION=${{ needs.build.outputs.version }}" >> $GITHUB_ENV 117 | echo "TG_API_VERSION=${{ needs.build.outputs.tg_api_version }}" >> $GITHUB_ENV 118 | echo "IMAGE=${{ needs.build.outputs.image }}" >> $GITHUB_ENV 119 | - name: Create and push manifest 120 | run: | 121 | # Create multi-arch manifests for all tags 122 | docker buildx imagetools create -t ${IMAGE}:${VERSION} \ 123 | ${IMAGE}:${VERSION}-linux-amd64 \ 124 | ${IMAGE}:${VERSION}-linux-arm64 125 | 126 | docker buildx imagetools create -t ${IMAGE}:${GITHUB_SHA::8} \ 127 | ${IMAGE}:${GITHUB_SHA::8}-linux-amd64 \ 128 | ${IMAGE}:${GITHUB_SHA::8}-linux-arm64 129 | 130 | docker buildx imagetools create -t ${IMAGE}:latest \ 131 | ${IMAGE}:${VERSION}-linux-amd64 \ 132 | ${IMAGE}:${VERSION}-linux-arm64 133 | 134 | docker buildx imagetools create -t ${IMAGE}:1.0.${GITHUB_RUN_NUMBER} \ 135 | ${IMAGE}:${VERSION}-linux-amd64 \ 136 | ${IMAGE}:${VERSION}-linux-arm64 137 | 138 | docker buildx imagetools create -t ${IMAGE}:api-${TG_API_VERSION} \ 139 | ${IMAGE}:${VERSION}-linux-amd64 \ 140 | ${IMAGE}:${VERSION}-linux-arm64 141 | - name: Inspect manifest 142 | run: | 143 | docker buildx imagetools inspect ${IMAGE}:${VERSION} 144 | docker buildx imagetools inspect ${IMAGE}:latest 145 | --------------------------------------------------------------------------------