Gitea with Let's Encrypt Using Docker Compose

This commit is contained in:
Vladimir Mikhalev
2023-09-01 18:31:13 -04:00
parent bfadd40ad7
commit ae60b92402
8 changed files with 565 additions and 108 deletions

View File

@@ -1,12 +1,62 @@
# Gitea with Let's Encrypt in a Docker Compose
# Gitea with Let's Encrypt Using Docker Compose
# The complete installation guide is available on my https://www.heyvaldemar.com/install-gitea-using-docker-compose/
# Change variables in the `.env` to meet your requirements.
# Note that the .env file should be in the same directory as `gitea-traefik-letsencrypt-docker-compose.yml`.
# Create networks for your services before deploying the configuration using the commands:
# `docker network create traefik-network`
# `docker network create gitea-network`
# Deploy Gitea using Docker Compose:
# `docker compose -f gitea-traefik-letsencrypt-docker-compose.yml -p gitea up -d`
# Backups
# The `backups` container in the configuration is responsible for the following:
# 1. **Database Backup**: Creates compressed backups of the PostgreSQL database using pg_dump.
# Customizable backup path, filename pattern, and schedule through variables like `POSTGRES_BACKUPS_PATH`, `POSTGRES_BACKUP_NAME`, and `BACKUP_INTERVAL`.
# 2. **Application Data Backup**: Compresses and stores backups of the application data on the same schedule. Controlled via variables such as `DATA_BACKUPS_PATH`, `DATA_BACKUP_NAME`, and `BACKUP_INTERVAL`.
# 3. **Backup Pruning**: Periodically removes backups exceeding a specified age to manage storage.
# Customizable pruning schedule and age threshold with `POSTGRES_BACKUP_PRUNE_DAYS` and `DATA_BACKUP_PRUNE_DAYS`.
# By utilizing this container, consistent and automated backups of the essential components of your instance are ensured.
# Moreover, efficient management of backup storage and tailored backup routines can be achieved through easy and flexible configuration using environment variables.
# # gitea-restore-database.sh Description
# This script facilitates the restoration of a database backup.
# 1. **Identify Containers**: It first identifies the service and backups containers by name, finding the appropriate container IDs.
# 2. **List Backups**: Displays all available database backups located at the specified backup path.
# 3. **Select Backup**: Prompts the user to copy and paste the desired backup name from the list to restore the database.
# 4. **Stop Service**: Temporarily stops the service to ensure data consistency during restoration.
# 5. **Restore Database**: Executes a sequence of commands to drop the current database, create a new one, and restore it from the selected compressed backup file.
# 6. **Start Service**: Restarts the service after the restoration is completed.
# To make the `gitea-restore-database.shh` script executable, run the following command:
# `chmod +x gitea-restore-database.sh`
# Usage of this script ensures a controlled and guided process to restore the database from an existing backup.
# # gitea-restore-application-data.sh Description
# This script is designed to restore the application data.
# 1. **Identify Containers**: Similarly to the database restore script, it identifies the service and backups containers by name.
# 2. **List Application Data Backups**: Displays all available application data backups at the specified backup path.
# 3. **Select Backup**: Asks the user to copy and paste the desired backup name for application data restoration.
# 4. **Stop Service**: Stops the service to prevent any conflicts during the restore process.
# 5. **Restore Application Data**: Removes the current application data and then extracts the selected backup to the appropriate application data path.
# 6. **Start Service**: Restarts the service after the application data has been successfully restored.
# To make the `gitea-restore-application-data.sh` script executable, run the following command:
# `chmod +x gitea-restore-application-data.sh`
# By utilizing this script, you can efficiently restore application data from an existing backup while ensuring proper coordination with the running service.
# Author
# hey, Im Vladimir Mikhalev, but my friends call me Valdemar.
# Im Vladimir Mikhalev, the Docker Captain, but my friends can call me Valdemar.
# https://www.docker.com/captains/vladimir-mikhalev/
# My website with detailed IT guides: https://www.heyvaldemar.com/
# Follow me on YouTube: https://www.youtube.com/channel/UCf85kQ0u1sYTTTyKVpxrlyQ?sub_confirmation=1
# Follow me on Twitter: https://twitter.com/heyValdemar
# Follow me on Instagram: https://www.instagram.com/heyvaldemar/
# Follow me on Threads: https://www.threads.net/@heyvaldemar
# Follow me on Mastodon: https://hachyderm.io/@heyValdemar
# Follow me on Bluesky: https://bsky.app/profile/heyvaldemar.bsky.social
# Follow me on Facebook: https://www.facebook.com/heyValdemarFB/
# Follow me on TikTok: https://www.tiktok.com/@heyvaldemar
# Follow me on LinkedIn: https://www.linkedin.com/in/heyvaldemar/
@@ -23,37 +73,33 @@
# Support on Ko-fi: https://ko-fi.com/heyValdemar
# Support on PayPal: https://www.paypal.com/paypalme/heyValdemarCOM
# Install Docker Engine and Docker Compose by following my guide: https://www.heyvaldemar.com/install-docker-engine-and-docker-compose-on-ubuntu-server/
# Run gitea-restore-application-data.sh to restore application data if needed.
# Run gitea-restore-database.sh to restore database if needed.
# Deploy Gitea server with a Docker Compose using the command:
# docker compose -f gitea-traefik-letsencrypt-docker-compose.yml -p gitea up -d
networks:
gitea-network:
external: true
traefik-network:
external: true
volumes:
gitea-data:
gitea-config:
gitea-postgres:
gitea-postgres-backup:
gitea-data-backups:
gitea-postgres-backups:
gitea-database-backups:
traefik-certificates:
services:
postgres:
# Image tag (replace with yours)
image: postgres:14
image: ${GITEA_POSTGRES_IMAGE_TAG}
volumes:
- gitea-postgres:/var/lib/postgresql/data
environment:
# Database name (replace with yours)
POSTGRES_DB: giteadb
# Database user (replace with yours)
POSTGRES_USER: giteadbuser
# Database password (replace with yours)
POSTGRES_PASSWORD: etFneCEtAWRKkfeQmkvwLWE
POSTGRES_DB: ${GITEA_DB_NAME}
POSTGRES_USER: ${GITEA_DB_USER}
POSTGRES_PASSWORD: ${GITEA_DB_PASSWORD}
networks:
- gitea-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -h 127.0.0.1"]
test: [ "CMD", "pg_isready", "-q", "-d", "${GITEA_DB_NAME}", "-U", "${GITEA_DB_USER}" ]
interval: 10s
timeout: 5s
retries: 3
@@ -61,28 +107,29 @@ services:
restart: unless-stopped
gitea:
# Image tag (replace with yours)
image: gitea/gitea:1.17
image: ${GITEA_IMAGE_TAG}
volumes:
- gitea-data:/data
- gitea-config:/etc/gitea
- gitea-data:/${DATA_PATH}
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
DB_TYPE: postgres
DB_HOST: postgres:5432
# Database name (replace with yours)
DB_NAME: giteadb
# Database user (replace with yours)
DB_USER: giteadbuser
# Database password (replace with yours)
DB_PASSWD: etFneCEtAWRKkfeQmkvwLWE
RUN_MODE: prod
SSH_PORT: 0
DISABLE_SSH: 'true'
HTTP_PORT: 3000
# Gitea URL (replace with yours)
ROOT_URL: https://gitea.heyvaldemar.net
GITEA_DATABASE_HOST: postgres
GITEA_DATABASE_NAME: ${GITEA_DB_NAME}
GITEA_DATABASE_USERNAME: ${GITEA_DB_USER}
GITEA_DATABASE_PASSWORD: ${GITEA_DB_PASSWORD}
GITEA_ADMIN_USER: ${GITEA_ADMIN_USERNAME}
GITEA_ADMIN_PASSWORD: ${GITEA_ADMIN_PASSWORD}
GITEA_ADMIN_EMAIL: ${GITEA_ADMIN_EMAIL}
GITEA_RUN_MODE: prod
GITEA_DOMAIN: ${GITEA_HOSTNAME}
GITEA_SSH_DOMAIN: ${GITEA_HOSTNAME}
GITEA_ROOT_URL: ${GITEA_URL}
GITEA_HTTP_PORT: 3000
GITEA_SSH_PORT: ${GITEA_SHELL_SSH_PORT}
GITEA_SSH_LISTEN_PORT: 22
networks:
- gitea-network
- traefik-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/"]
interval: 10s
@@ -91,8 +138,7 @@ services:
start_period: 90s
labels:
- "traefik.enable=true"
# Gitea URL (replace with yours)
- "traefik.http.routers.gitea.rule=Host(`gitea.heyvaldemar.net`)"
- "traefik.http.routers.gitea.rule=Host(`${GITEA_HOSTNAME}`)"
- "traefik.http.routers.gitea.service=gitea"
- "traefik.http.routers.gitea.entrypoints=websecure"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
@@ -101,6 +147,11 @@ services:
- "traefik.http.services.gitea.loadbalancer.passhostheader=true"
- "traefik.http.routers.gitea.middlewares=compresstraefik"
- "traefik.http.middlewares.compresstraefik.compress=true"
- "traefik.tcp.routers.gitea-ssh.rule=HostSNI(`*`)"
- "traefik.tcp.routers.gitea-ssh.service=gitea-ssh"
- "traefik.tcp.routers.gitea-ssh.entrypoints=ssh"
- "traefik.tcp.services.gitea-ssh.loadbalancer.server.port=22"
- "traefik.docker.network=traefik-network"
restart: unless-stopped
depends_on:
postgres:
@@ -109,10 +160,9 @@ services:
condition: service_healthy
traefik:
# Image tag (replace with yours)
image: traefik:2.8
image: ${TRAEFIK_IMAGE_TAG}
command:
- "--log.level=WARN"
- "--log.level=${TRAEFIK_LOG_LEVEL}"
- "--accesslog=true"
- "--api.dashboard=true"
- "--api.insecure=true"
@@ -121,12 +171,12 @@ services:
- "--entryPoints.ping.address=:8082"
- "--entryPoints.web.address=:80"
- "--entryPoints.websecure.address=:443"
- "--entryPoints.ssh.address=:${GITEA_SHELL_SSH_PORT}"
- "--providers.docker=true"
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.exposedByDefault=false"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
# Email for Let's Encrypt (replace with yours)
- "--certificatesresolvers.letsencrypt.acme.email=callvaldemar@gmail.com"
- "--certificatesresolvers.letsencrypt.acme.email=${TRAEFIK_ACME_EMAIL}"
- "--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json"
- "--metrics.prometheus=true"
- "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0"
@@ -135,7 +185,10 @@ services:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- traefik-certificates:/etc/traefik/acme
networks:
- traefik-network
ports:
- "${GITEA_SHELL_SSH_PORT}:${GITEA_SHELL_SSH_PORT}"
- "80:80"
- "443:443"
healthcheck:
@@ -146,8 +199,7 @@ services:
start_period: 5s
labels:
- "traefik.enable=true"
# Traefik URL (replace with yours)
- "traefik.http.routers.dashboard.rule=Host(`traefik.gitea.heyvaldemar.net`)"
- "traefik.http.routers.dashboard.rule=Host(`${TRAEFIK_HOSTNAME}`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.services.dashboard.loadbalancer.server.port=8080"
@@ -155,10 +207,7 @@ services:
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.services.dashboard.loadbalancer.passhostheader=true"
- "traefik.http.routers.dashboard.middlewares=authtraefik"
# Basic Authentication for Traefik Dashboard
# Username: traefikadmin (replace with yours)
# Passwords must be encoded using MD5, SHA1, or BCrypt https://hostingcanada.org/htpasswd-generator/
- "traefik.http.middlewares.authtraefik.basicauth.users=traefikadmin:$$2y$$10$$sMzJfirKC75x/hVpiINeZOiSm.Jkity9cn4KwNkRvO7hSQVFc5FLO"
- "traefik.http.middlewares.authtraefik.basicauth.users=${TRAEFIK_BASIC_AUTH}"
- "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
@@ -166,43 +215,36 @@ services:
restart: unless-stopped
backups:
# Image tag (replace with yours)
image: postgres:14
# Database backups prune interval (replace with yours). Default is 7 days.
# find /srv/gitea-postgres/backups -type f -mtime +7 | xargs rm -f
# Application data backups prune interval (replace with yours). Default is 7 days.
# find /srv/gitea-application-data/backups -type f -mtime +7 | xargs rm -f
# Gitea backups interval (replace with yours). Default is 1 day.
# sleep 24h
# Run gitea-restore-application-data.sh to restore application data if needed.
# Run gitea-restore-database.sh to restore database if needed.
command: sh -c 'sleep 30m
&& while true; do
PGPASSWORD="$$(echo $$POSTGRES_PASSWORD)"
pg_dump
-h postgres
-p 5432
-d giteadb
-U giteadbuser | gzip > /srv/gitea-postgres/backups/gitea-postgres-backup-$$(date "+%Y-%m-%d_%H-%M").gz
&& tar -zcpf /srv/gitea-application-data/backups/gitea-application-data-backup-$$(date "+%Y-%m-%d_%H-%M").tar.gz /etc/gitea
&& find /srv/gitea-postgres/backups -type f -mtime +7 | xargs rm -f
&& find /srv/gitea-application-data/backups -type f -mtime +7 | xargs rm -f;
sleep 24h; done'
image: ${GITEA_POSTGRES_IMAGE_TAG}
command: >-
sh -c 'sleep $BACKUP_INIT_SLEEP &&
while true; do
pg_dump -h postgres -p 5432 -d $GITEA_DB_NAME -U $GITEA_DB_USER | gzip > $POSTGRES_BACKUPS_PATH/$POSTGRES_BACKUP_NAME-$(date "+%Y-%m-%d_%H-%M").gz &&
tar -zcpf $DATA_BACKUPS_PATH/$DATA_BACKUP_NAME-$(date "+%Y-%m-%d_%H-%M").tar.gz $DATA_PATH &&
find $POSTGRES_BACKUPS_PATH -type f -mtime +$POSTGRES_BACKUP_PRUNE_DAYS | xargs rm -f &&
find $DATA_BACKUPS_PATH -type f -mtime +$DATA_BACKUP_PRUNE_DAYS | xargs rm -f;
sleep $BACKUP_INTERVAL; done'
volumes:
- gitea-data:/etc/gitea
# Application data backups location
- gitea-data-backups:/srv/gitea-application-data/backups
# Database backups location
- gitea-postgres-backups:/srv/gitea-postgres/backups
- gitea-postgres-backup:/var/lib/postgresql/data
- gitea-data:${DATA_PATH}
- gitea-data-backups:${DATA_BACKUPS_PATH}
- gitea-database-backups:${POSTGRES_BACKUPS_PATH}
environment:
# Database password (replace with yours)
POSTGRES_PASSWORD: etFneCEtAWRKkfeQmkvwLWE
GITEA_DB_NAME: ${GITEA_DB_NAME}
GITEA_DB_USER: ${GITEA_DB_USER}
PGPASSWORD: ${GITEA_DB_PASSWORD}
BACKUP_INIT_SLEEP: ${BACKUP_INIT_SLEEP}
BACKUP_INTERVAL: ${BACKUP_INTERVAL}
POSTGRES_BACKUP_PRUNE_DAYS: ${POSTGRES_BACKUP_PRUNE_DAYS}
DATA_BACKUP_PRUNE_DAYS: ${DATA_BACKUP_PRUNE_DAYS}
POSTGRES_BACKUPS_PATH: ${POSTGRES_BACKUPS_PATH}
DATA_BACKUPS_PATH: ${DATA_BACKUPS_PATH}
DATA_PATH: ${DATA_PATH}
POSTGRES_BACKUP_NAME: ${POSTGRES_BACKUP_NAME}
DATA_BACKUP_NAME: ${DATA_BACKUP_NAME}
networks:
- gitea-network
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
gitea:
condition: service_healthy