├── .gitignore ├── README.md ├── backup.py ├── docker-compose.yml ├── restore_dump.sh └── take_dump.sh /.gitignore: -------------------------------------------------------------------------------- 1 | gitea_database/ 2 | gitea/ 3 | *.zip 4 | .env 5 | .env.db 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dev server 2 | 3 | ## Setup 4 | 5 | Requirements: 6 | 7 | ```bash 8 | sudo apt update -y && sudo apt install -y docker docker-compose python3 python3-pip vim git 9 | pip3 install boto3 10 | ``` 11 | 12 | Create `~/.aws/` with credentials: 13 | 14 | ```bash 15 | mkdir ~/.aws/ 16 | vim ~/.aws/credentials 17 | vim ~/.aws/config 18 | ``` 19 | 20 | File `credentials`: 21 | 22 | ``` 23 | [default] 24 | aws_access_key_id = <идентификатор_статического_ключа> 25 | aws_secret_access_key = <секретный_ключ> 26 | 27 | ``` 28 | 29 | File `config`: 30 | 31 | ``` 32 | [default] 33 | region=ru-central1 34 | 35 | ``` 36 | 37 | Clone a repo: 38 | 39 | ```bash 40 | git clone https://git.area51-lab.ru/architect/dev_server 41 | cd dev_server 42 | ``` 43 | 44 | ## Deploy 45 | 46 | Create `.env` file: 47 | 48 | ```yaml 49 | USER_UID=1000 50 | USER_GID=1000 51 | GITEA__database__DB_TYPE=postgres 52 | GITEA__database__HOST=gitea_db 53 | GITEA__database__NAME=gitea 54 | GITEA__database__USER=git3453453463456 55 | GITEA__database__PASSWD=9ew4hyfr97e84trye4tregiytetreir7ftye 56 | GITEA__mailer__ENABLED=true 57 | GITEA__mailer__FROM=area51-lab@yandex.ru 58 | GITEA__mailer__PROTOCOL=smtps 59 | GITEA__mailer__SMTP_ADDR=smtp.yandex.ru 60 | GITEA__mailer__SMTP_PORT=465 61 | GITEA__mailer__USER=area51-lab 62 | GITEA__mailer__PASSWD=shyiacppxexzurax 63 | GITEA__ui__THEMES=gitea,arc-green 64 | GITEA__ui__DEFAULT_THEME=arc-green 65 | ``` 66 | 67 | Create `.env.db` file: 68 | 69 | ```yaml 70 | POSTGRES_USER=git3453453463456 71 | POSTGRES_PASSWORD=9ew4hyfr97e84trye4tregiytetreir7ftye 72 | POSTGRES_DB=gitea 73 | ``` 74 | 75 | Run: 76 | 77 | ```bash 78 | sudo docker-compose up -d --build 79 | ``` 80 | 81 | ## Reverse proxy 82 | 83 | Default nginx config `/etc/nginx/sites-available/default`: 84 | 85 | ```bash 86 | sudo rm /etc/nginx/sites-available/default 87 | sudo vim /etc/nginx/sites-available/default 88 | ``` 89 | 90 | Set: 91 | 92 | ```nginx 93 | upstream git { 94 | server 127.0.0.1:3000; 95 | } 96 | 97 | server { 98 | listen 80; 99 | return 301 https://$host$request_uri; 100 | } 101 | 102 | server { 103 | listen 443 ssl; 104 | server_name git.area51-lab.ru; 105 | 106 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 107 | ssl_prefer_server_ciphers on; 108 | ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS; 109 | ssl_certificate /etc/ssl/mycert.crt; 110 | ssl_certificate_key /etc/ssl/mykey.key; 111 | 112 | client_body_buffer_size 32k; 113 | client_header_buffer_size 8k; 114 | large_client_header_buffers 8 64k; 115 | 116 | client_max_body_size 30g; 117 | 118 | access_log /var/log/nginx/nginx-git-access.log; 119 | error_log /var/log/nginx/nginx-git-error.log; 120 | 121 | location / { 122 | proxy_pass http://git; 123 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 124 | proxy_set_header Host $host; 125 | proxy_redirect off; 126 | } 127 | } 128 | 129 | ``` 130 | 131 | Restart Nginx: 132 | 133 | ```bash 134 | sudo systemctl restart nginx 135 | sudo systemctl status nginx 136 | ``` 137 | 138 | ## Make backup 139 | 140 | Create backup: 141 | 142 | ```bash 143 | ./take_dump.sh 144 | ``` 145 | 146 | Upload it to S3: 147 | 148 | ```bash 149 | python3 backup.py -u 150 | ``` 151 | 152 | And yes... 153 | 154 | ``` 155 | Every where write backup name without extension! 156 | ``` 157 | 158 | ## Restore backup 159 | 160 | Get backup from S3: 161 | 162 | ```bash 163 | python3 backup.py -d 164 | ``` 165 | 166 | Run a clear stack: 167 | 168 | ```bash 169 | sudo docker-compose up -d --build 170 | ``` 171 | 172 | Then restore downloaded backup: 173 | 174 | ```bash 175 | ./restore_dump.sh 176 | ``` 177 | 178 | ## Cleanup 179 | 180 | ```bash 181 | rm *.zip 182 | sudo docker-compose down -v 183 | sudo docker system prune -a 184 | sudo rm -rf gitea/ gitea_database/ 185 | ``` 186 | -------------------------------------------------------------------------------- /backup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #-*- coding: utf-8 -*- 3 | 4 | import boto3 5 | import botocore 6 | import logging 7 | import argparse 8 | 9 | 10 | console_logger = logging.StreamHandler() 11 | 12 | logging.basicConfig(handlers=(console_logger,), 13 | format='[%(asctime)s | %(levelname)s]: %(message)s', 14 | datefmt='%m.%d.%Y %H:%M:%S', 15 | level=logging.INFO) 16 | 17 | session = boto3.session.Session() 18 | 19 | BUCKET = 'area51-git-backup' 20 | 21 | 22 | if __name__ == '__main__': 23 | 24 | s3 = session.client( 25 | service_name='s3', 26 | endpoint_url='https://storage.yandexcloud.net' 27 | ) 28 | 29 | parser = argparse.ArgumentParser(description="Automated backup and restore Gitea with Yandex Cloud S3.") 30 | group = parser.add_mutually_exclusive_group(required=True) 31 | group.add_argument('-u', '--upload', help="New backup name. Zip-file name equals S3 key of backup.") 32 | group.add_argument('-d', '--download', help="Backup key in S3") 33 | args = parser.parse_args() 34 | 35 | if args.upload: 36 | logging.info(f"Uploading backup: {args.upload}") 37 | 38 | try: 39 | s3.upload_file(f"{args.upload}.zip", BUCKET, args.upload) 40 | 41 | except: 42 | logging.critical(f"No backup file {args.upload}.zip") 43 | exit(1) 44 | 45 | logging.info("OK") 46 | 47 | elif args.download: 48 | logging.info(f"Downloading backup: {args.download}") 49 | 50 | try: 51 | s3.download_file(BUCKET, args.download, f"{args.download}.zip") 52 | 53 | except botocore.exceptions.NoCredentialsError: 54 | logging.critical("Backup not found in storage.") 55 | exit(1) 56 | 57 | logging.info("OK") 58 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | <<<<<<< HEAD 2 | <<<<<<< HEAD 3 | version: '3' 4 | 5 | services: 6 | 7 | gitea: 8 | image: gitea/gitea:latest 9 | container_name: gitea 10 | env_file: 11 | - ./.env 12 | restart: always 13 | expose: 14 | - 3000 15 | volumes: 16 | - ./gitea:/data 17 | - /etc/timezone:/etc/timezone:ro 18 | - /etc/localtime:/etc/localtime:ro 19 | networks: 20 | areanet: 21 | ipv4_address: 172.16.0.2 22 | healthcheck: 23 | test: curl -fSs 127.0.0.1:3000/api/v1/health || exit 1 24 | interval: 20s 25 | timeout: 10s 26 | retries: 3 27 | 28 | gitea_db: 29 | image: postgres:14 30 | container_name: gitea_database 31 | env_file: 32 | - ./.env.db 33 | restart: always 34 | expose: 35 | - 5432 36 | volumes: 37 | - ./gitea_database:/var/lib/postgresql/data 38 | networks: 39 | areanet: 40 | ipv4_address: 172.16.0.3 41 | healthcheck: 42 | test: pg_isready 43 | interval: 20s 44 | timeout: 5s 45 | retries: 3 46 | 47 | networks: 48 | areanet: 49 | driver: bridge 50 | ipam: 51 | driver: default 52 | config: 53 | - subnet: "172.16.0.0/28" 54 | ======= 55 | version: '3' 56 | 57 | services: 58 | 59 | gitea: 60 | image: gitea/gitea:latest 61 | env_file: 62 | - ./.env 63 | restart: always 64 | ports: 65 | - "127.0.0.1:3000:3000" 66 | volumes: 67 | - ./gitea:/data 68 | - /etc/timezone:/etc/timezone:ro 69 | - /etc/localtime:/etc/localtime:ro 70 | networks: 71 | - areanet 72 | healthcheck: 73 | test: curl -fSs localhost:3000 || exit 1 74 | interval: 60s 75 | timeout: 10s 76 | retries: 3 77 | 78 | gitea_db: 79 | image: postgres:14 80 | container_name: gitea_database 81 | env_file: 82 | - ./.env.db 83 | restart: always 84 | expose: 85 | - 5432 86 | volumes: 87 | - ./gitea_database:/var/lib/postgresql/data 88 | networks: 89 | - areanet 90 | healthcheck: 91 | test: pg_isready 92 | interval: 60s 93 | timeout: 5s 94 | retries: 3 95 | 96 | networks: 97 | areanet: 98 | driver: bridge 99 | ipam: 100 | driver: default 101 | config: 102 | - subnet: "172.16.0.0/28" 103 | >>>>>>> 49d95b7 (update) 104 | ======= 105 | version: '3' 106 | 107 | services: 108 | 109 | gitea: 110 | image: gitea/gitea:latest 111 | env_file: 112 | - ./.env 113 | restart: always 114 | ports: 115 | - "127.0.0.1:3000:3000" 116 | volumes: 117 | - gitea:/data 118 | - /etc/timezone:/etc/timezone:ro 119 | - /etc/localtime:/etc/localtime:ro 120 | networks: 121 | - areanet 122 | healthcheck: 123 | test: curl -fSs localhost:3000 || exit 1 124 | interval: 60s 125 | timeout: 10s 126 | retries: 3 127 | 128 | gitea_db: 129 | image: postgres:14 130 | container_name: gitea_database 131 | env_file: 132 | - ./.env.db 133 | restart: always 134 | expose: 135 | - 5432 136 | volumes: 137 | - ./gitea_database:/var/lib/postgresql/data 138 | networks: 139 | - areanet 140 | healthcheck: 141 | test: pg_isready 142 | interval: 60s 143 | timeout: 5s 144 | retries: 3 145 | 146 | networks: 147 | areanet: 148 | driver: bridge 149 | ipam: 150 | driver: default 151 | config: 152 | - subnet: "172.16.0.0/28" 153 | >>>>>>> f73f4cc (update: Readme.md) 154 | -------------------------------------------------------------------------------- /restore_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -n "Backup name: " 4 | read filename 5 | 6 | sudo docker cp $filename.zip gitea_database:/tmp/dump.zip 7 | sudo docker-compose exec gitea_db apt update -y 8 | sudo docker-compose exec gitea_db apt install -y unzip 9 | sudo docker-compose exec -w /tmp/ gitea_db mkdir dump 10 | sudo docker-compose exec -w /tmp/ gitea_db unzip dump.zip -d dump/ 11 | sudo docker-compose exec -w /tmp/dump/ gitea_db bash -c 'psql -d $POSTGRES_DB -U $POSTGRES_USER -f gitea-db.sql' 12 | sudo docker-compose exec -w /tmp/ gitea_db rm dump.zip 13 | sudo docker-compose exec -w /tmp/ gitea_db rm -rf dump/ 14 | sudo docker cp $filename.zip gitea:/app/gitea/dump.zip 15 | sudo docker-compose exec -w /app/gitea/ gitea mkdir dump 16 | sudo docker-compose exec -w /app/gitea/ gitea unzip dump.zip -d dump/ 17 | #sudo docker-compose exec -w /app/gitea/dump/ gitea cp app.ini /data/gitea/conf/app.ini 18 | sudo docker-compose exec -w /app/gitea/dump/ gitea cp -R data/. /data/gitea 19 | sudo docker-compose exec -w /app/gitea/dump/ gitea cp -R repos/. /data/git/gitea-repositories/ 20 | sudo docker-compose exec -w /app/gitea/dump/ gitea cp -R repos/. /data/git/repositories 21 | sudo docker-compose exec -w /app/gitea/dump/ gitea chown -R git:git /data/gitea/conf/app.ini /data /data/git/repositories 22 | sudo docker-compose exec -w /app/gitea/ gitea rm dump.zip 23 | sudo docker-compose exec -w /app/gitea/ gitea rm -rf dump/ 24 | sudo docker-compose restart 25 | -------------------------------------------------------------------------------- /take_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -n "New backup name: " 4 | read filename 5 | USER=$(whoami) 6 | 7 | sudo docker-compose exec -u git -w /app/gitea/ gitea bash -c '/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini --file dump.zip' 8 | sudo docker cp gitea:/app/gitea/dump.zip $filename.zip 9 | sudo docker-compose exec -u git -w /app/gitea/ gitea rm dump.zip 10 | sudo chown $USER:$USER $filename.zip 11 | --------------------------------------------------------------------------------