10-minute Weblate setup using docker-compose & Traefik

See Simple Traefik docker-compose setup with Lets Encrypt Cloudflare DNS-01 & TLS-ALPN-01 & HTTP-01 challenges for the Trafik config we use.

All data for weblate, including the database, will be stored in mapped directories, as opposed to Docker volumes. This keeps all the data together.

First create the directory, e.g. /opt/weblate.

`docker-compose.yml

Now create /opt/weblate/docker-compose.yml

services:
  weblate:
    image: weblate/weblate
    tmpfs:
      - /run
      - /tmp
    volumes:
      - ./weblate_data:/app/data
      - ./weblate_cache:/app/cache
    restart: always
    read_only: true
    depends_on:
      - database
      - cache
    env_file:
      - .env
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.weblate-mydomain.rule=Host(`weblate.mydomain.com`)"
      - "traefik.http.routers.weblate-mydomain.entrypoints=websecure"
      - "traefik.http.routers.weblate-mydomain.tls.certresolver=cloudflare-ec384"
      - "traefik.http.routers.weblate-mydomain.tls.domains[0].main=mydomain.com"
      - "traefik.http.routers.weblate-mydomain.tls.domains[0].sans=*.mydomain.com"
      - "traefik.http.services.weblate-mydomain.loadbalancer.server.port=8080"
  database:
    image: postgres:16-alpine
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_DB=${POSTGRES_DB}

    restart: always
  cache:
    image: redis:7-alpine
    restart: always
    read_only: true
    env_file:
      - .env
    command: [redis-server, --save, '60', '1']
    volumes:
      - ./redis_data:/data

Initialize

Run this shell script in /opt/weblate:

#!/bin/sh
mkdir -p weblate_data weblate_cache
chown -R 1000:1000 weblate_data weblate_cache

to create the necessary directories and set the correct permissions.

Create .env (the config file)

See the Weblate Docker docs for more info on all available options. For this example, we only show all enabled config options.

Create this as /opt/weblate/.env.

Note that, by default, I set it as not open for registration, but requires login. This is the most common configuration for private / corporate setups where the admin will manage user accounts manually.

WEBLATE_SITE_DOMAIN=weblate.mydomain.com
WEBLATE_DEBUG=0
WEBLATE_LOGLEVEL=INFO
WEBLATE_SITE_TITLE=Weblate Techoverflow
WEBLATE_ADMIN_NAME=uli
WEBLATE_ADMIN_EMAIL=[email protected]
WEBLATE_ADMIN_PASSWORD=Uditien0og9ohshohg0Ooj7XooC0io
WEBLATE_SERVER_EMAIL=[email protected]
WEBLATE_DEFAULT_FROM_EMAIL=[email protected]
WEBLATE_ALLOWED_HOSTS=*
WEBLATE_REGISTRATION_OPEN=0
WEBLATE_TIME_ZONE=Europe/Berlin
WEBLATE_IP_PROXY_HEADER=HTTP_X_FORWARDED_FOR
WEBLATE_REQUIRE_LOGIN=1
POSTGRES_PASSWORD=gahth9Geasautheejee8kies9sheeb
POSTGRES_USER=weblate
POSTGRES_DB=weblate
POSTGRES_HOST=database
POSTGRES_DATABASE=weblate
REDIS_HOST=cache
REDIS_PORT=6379
WEBLATE_EMAIL_HOST=mail.mydomain.com
WEBLATE_EMAIL_HOST_USER=[email protected]
WEBLATE_EMAIL_HOST_PASSWORD=Oora5phaej
CLIENT_MAX_BODY_SIZE=200M
WEBLATE_SECURE_PROXY_SSL_HEADER=HTTP_X_FORWARDED_PROTO,https

Setup autostart

TL;DR: Run this in /opt/weblate

curl -fsSL https://techoverflow.net/scripts/create-docker-compose-service.sh | sudo bash /dev/stdin

See Create a systemd service for your docker-compose project in 10 seconds for more details.

Setup using the webinterface

Now open https://weblate.mydomain.com and follow the on-screen instructions to complete the setup.