merge changes
ci / docker (push) Failing after 4m41s

This commit is contained in:
Andreas Martin
2026-05-06 19:02:04 +02:00
32 changed files with 1252 additions and 202 deletions
+1
View File
@@ -23,4 +23,5 @@
# MAIL_TO=""
# MAIL_WHEN_SUCCESS="TRUE"
# MAIL_WHEN_FAILURE="TRUE"
# MAIL_FORCE_THREAD="FALSE"
# TIMEZONE="UTC"
+1
View File
@@ -0,0 +1 @@
/*.hcl linguist-detectable=false
+255
View File
@@ -1,5 +1,260 @@
# Changelog
## v1.26.8 (20260502)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.74.0`
<br>
## v1.26.7 (20260421)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.73.5`
<br>
## v1.26.6 (20260409)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.73.4`
<br>
## v1.26.5 (20260325)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.73.3`
<br>
## v1.26.4 (20260317)
### Fixed
- Fix unable to validate encrypted Rclone config (fixed [#229](https://github.com/ttionya/vaultwarden-backup/issues/229))
<br>
## v1.26.3 (20260307)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.73.2`
<br>
## v1.26.2 (20260219)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.73.1`
<br>
## v1.26.1 (20260131)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.73.0`
<br>
## v1.26.0 (20251213)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.72.1`
- Support PostgreSQL 18 (close [#223](https://github.com/ttionya/vaultwarden-backup/issues/223))
<br>
## v1.25.4 (20251122)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.72.0`
### Fixed
- Fix the incorrect generation of the Message-ID (fixed [#220](https://github.com/ttionya/vaultwarden-backup/issues/220))
<br>
## v1.25.3 (20251023)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.71.2`
- Accurately distinguish between an unconfigured Rclone and the use of illegal Rclone flags (fixed [#205](https://github.com/ttionya/vaultwarden-backup/issues/205))
<br>
## v1.25.2 (20250928)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.71.1`
<br>
## v1.25.1 (20250823)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.71.0`
<br>
## v1.25.0 (20250802)
### Feature
- Add environment variable `MAIL_FORCE_THREAD` to control email threading (close [#210](https://github.com/ttionya/vaultwarden-backup/issues/210))
<br>
## v1.24.4 (20250712)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.70.3`
<br>
## v1.24.3 (20250522)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.69.3`
<br>
## v1.24.2 (20250512)
### Fixed
- Fix `directory not found` error (fixed [#199](https://github.com/ttionya/vaultwarden-backup/issues/199))
<br>
## v1.24.1 (20250503)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.69.2`
<br>
## v1.24.0 (20250316)
### Feature
- Add environment variable `DISPLAY_NAME` to customize the display name (close [#189](https://github.com/ttionya/vaultwarden-backup/issues/189))
<br>
## v1.23.2 (20250312)
### Fixed
- Fix the issue where errors occur due to spaces in `MAIL_SMTP_VARIABLES` in some cases (fixed [#186](https://github.com/ttionya/vaultwarden-backup/issues/186))
<br>
## v1.23.1 (20250220)
### Feature
- Add environment variables `MYSQL_SSL` and `MYSQL_SSL_VERIFY_SERVER_CERT` to resolve the MySQL TLS connection error
<br>
## v1.23.0 (20250218)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.69.1`
- Support MySQL SSL connection (close [#185](https://github.com/ttionya/vaultwarden-backup/pull/185))
- Optimize Rclone connection detection logic (close [#183](https://github.com/ttionya/vaultwarden-backup/issues/183))
### Chore
- Compatible with docker/bake-action@v6
<br>
## v1.22.0 (20250116)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.69.0`
- Support PostgreSQL 17 (close [#178](https://github.com/ttionya/vaultwarden-backup/issues/178))
- Allow partial storage system connection failures during backup verification (close [#175](https://github.com/ttionya/vaultwarden-backup/issues/175))
<br>
## v1.21.3 (20241117)
### Feature
- Update Dockerfile base image to `rclone/rclone:1.68.2`
- Use standardized docker labels
<br>
## v1.21.2 (20240925)
### Feature
+3 -2
View File
@@ -1,5 +1,6 @@
FROM rclone/rclone:1.68.1
# syntax=docker/dockerfile:1
FROM rclone/rclone:1.74.0
LABEL "repository"="git.ow7.de/martinan/vaultwarden-backup:latest" \
"homepage"="https://git.ow7.de/martinan/vaultwarden-backup" \
"maintainer"="Andreas Martin <andreas.martin@gmx.net>"
@@ -13,7 +14,7 @@ COPY scripts/*.sh /app/
RUN chmod +x /app/*.sh \
&& mkdir -m 777 /bitwarden \
&& apk add --no-cache 7zip bash curl mariadb-client postgresql16-client sqlite supercronic s-nail tzdata \
&& apk add --no-cache 7zip bash curl mariadb-client postgresql18-client sqlite supercronic s-nail tzdata \
&& apk info --no-cache -Lq mariadb-client | grep -vE '/bin/mariadb$' | grep -vE '/bin/mariadb-dump$' | xargs -I {} rm -f "/{}" \
&& ln -sf "${LOCALTIME_FILE}" /etc/localtime \
&& addgroup -g "${USER_ID}" "${USER_NAME}" \
+70 -53
View File
@@ -314,6 +314,14 @@ Here is timezone list at [wikipedia](https://en.wikipedia.org/wiki/List_of_tz_da
Default: `UTC`
#### DISPLAY_NAME
A custom name to identify your vaultwarden instance in notifications and logs.
This doesn't affect functionality, it only affects the display in the notification title and partial log output.
Default: `vaultwarden`
#### DATA_DIR
This folder stores the data of vaultwarden.
@@ -384,56 +392,6 @@ Default: `${DATA_DIR}/sends`
## Notification
### Mail
Starting from v1.19.0, we will be using [`s-nail`](https://www.sdaoden.eu/code-nail.html) instead of [`heirloom-mailx`](https://www.systutorials.com/docs/linux/man/1-heirloom-mailx/) to send emails.
Please note that `heirloom-mailx` is a stub for `s-nail`, and most of its functionality is compatible. Therefore, you may not need to modify any environment variables for this change.
| Environment Variable | Default Value | Description |
| --- | --- |-------------------------------------------------------|
| MAIL_SMTP_ENABLE | `FALSE` | Enable sending mail. |
| MAIL_SMTP_VARIABLES | | Mail sending options. |
| MAIL_TO | | The recipient of the notification email. |
| MAIL_WHEN_SUCCESS | `TRUE` | Send an email when the backup completes successfully. |
| MAIL_WHEN_FAILURE | `TRUE` | Send an email if the backup fails. |
For `MAIL_SMTP_VARIABLES`, you need to configure the mail sending options yourself. **We will set the email subject based on the usage scenario, so you should not use the `-s` flag.**
```text
# My example:
# For Zoho
-S smtp-use-starttls \
-S smtp=smtp://smtp.zoho.com:587 \
-S smtp-auth=login \
-S smtp-auth-user=<my-email-address> \
-S smtp-auth-password=<my-email-password> \
-S from=<my-email-address>
```
Console showing warnings? Check [issue #177](https://github.com/ttionya/vaultwarden-backup/issues/117#issuecomment-1691443179) for more details.
<br>
### Mail Test
You can use the following command to test mail sending. We will add the `-v` flag to display detailed information, so you do not need to set it again in `MAIL_SMTP_VARIABLES`.
```shell
docker run --rm -it -e MAIL_SMTP_VARIABLES='<your smtp variables>' ttionya/vaultwarden-backup:latest mail <mail send to>
# Or
docker run --rm -it -e MAIL_SMTP_VARIABLES='<your smtp variables>' -e MAIL_TO='<mail send to>' ttionya/vaultwarden-backup:latest mail
```
<br>
### Ping
We provide functionality to send notifications when the backup is completed, started, successful, or failed.
@@ -480,6 +438,65 @@ docker run --rm -it \
### Mail
Starting from v1.19.0, we will be using [`s-nail`](https://www.sdaoden.eu/code-nail.html) instead of [`heirloom-mailx`](https://www.systutorials.com/docs/linux/man/1-heirloom-mailx/) to send emails.
Please note that `heirloom-mailx` is a stub for `s-nail`, and most of its functionality is compatible. Therefore, you may not need to modify any environment variables for this change.
| Environment Variable | Default Value | Description |
| --- | --- |-----------------------------------------------------------------------------------------------------------------------|
| MAIL_SMTP_ENABLE | `FALSE` | Enable sending mail. |
| MAIL_SMTP_VARIABLES | | Mail sending options. |
| MAIL_TO | | The recipient of the notification email. |
| MAIL_WHEN_SUCCESS | `TRUE` | Send an email when the backup completes successfully. |
| MAIL_WHEN_FAILURE | `TRUE` | Send an email if the backup fails. |
| MAIL_FORCE_THREAD | `FALSE` | Particularly useful when mail clients fail to group related messages in conversation view despite identical subjects. |
For `MAIL_SMTP_VARIABLES`, you need to configure the mail sending options yourself. **We will set the email subject based on the usage scenario, so you should not use the `-s` flag.**
```text
# My example:
# For Zoho
-S smtp-use-starttls \
-S smtp=smtp://smtp.zoho.com:587 \
-S smtp-auth=login \
-S smtp-auth-user=<my-email-address> \
-S smtp-auth-password=<my-email-password> \
-S from=<my-email-address>
```
Console showing warnings? Check [issue #177](https://github.com/ttionya/vaultwarden-backup/issues/117#issuecomment-1691443179) for more details.
For `MAIL_FORCE_THREAD`, particularly useful when receiving systems fail to properly aggregate messages into conversation threads. It supports three modes of operation:
1. `FALSE`: Default email sending behavior.
2. `TRUE`: Auto-generates RFC-compliant Message-ID to force thread creation.
3. `Valid Message-ID string`: Uses specified Message-ID to associate with existing thread. Find it in the original email's Message-ID field.
When enabled, the system automatically adds required headers (`Message-ID`, `References`, `In-Reply-To`) to enforce proper thread association on the receiving end.
<br>
### Mail Test
You can use the following command to test mail sending. We will add the `-v` flag to display detailed information, so you do not need to set it again in `MAIL_SMTP_VARIABLES`.
```shell
docker run --rm -it -e MAIL_SMTP_VARIABLES='<your smtp variables>' ttionya/vaultwarden-backup:latest mail <mail send to>
# Or
docker run --rm -it -e MAIL_SMTP_VARIABLES='<your smtp variables>' -e MAIL_TO='<mail send to>' ttionya/vaultwarden-backup:latest mail
```
<br>
## Environment Variables Considerations
### Using `.env` file
@@ -531,10 +548,10 @@ MY_ENV="example1"
MY_ENV_FILE="/path/to/example2"
# For 3 (.env file)
MY_ENV_FILE: "/path/to/example3"
MY_ENV_FILE="/path/to/example3"
# For 4 (.env file)
MY_ENV: "example4"
MY_ENV="example4"
```
<br>
@@ -583,7 +600,7 @@ Check out the [CHANGELOG](CHANGELOG.md) file.
I am grateful for the OSS license provided by [JetBrains](https://www.jetbrains.com/).
<a href="https://jb.gg/OpenSourceSupport" target="_blank"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" alt="JetBrains Logo (Main) logo" width="200"></a>
<a href="https://jb.gg/OpenSource" target="_blank"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" alt="JetBrains logo."></a>
<br>
+70 -53
View File
@@ -312,6 +312,14 @@ Rclone 全局参数,详见 [flags](https://rclone.org/flags/)。
默认值:`UTC`
#### DISPLAY_NAME
用于在通知和日志中标识 vaultwarden 实例的自定义名称。
这不会影响功能,仅影响通知标题和部分日志输出中的显示。
默认值:`vaultwarden`
#### DATA_DIR
指定存放 vaultwarden 数据的目录。
@@ -381,56 +389,6 @@ Default: `%Y%m%d`
## 通知
### Mail
从 v1.19.0 开始,本工具使用 [`s-nail`](https://www.sdaoden.eu/code-nail.html) 代替 [`heirloom-mailx`](https://www.systutorials.com/docs/linux/man/1-heirloom-mailx/) 发送邮件。
请注意,`heirloom-mailx``s-nail` 的存根,它们大部分功能是兼容的。因此你可能不需要为这个改变修改任何环境变量。
| 环境变量 | 默认值 | 描述 |
| --- |--------|-----------|
| MAIL_SMTP_ENABLE | `FALSE` | 启用邮件发送功能 |
| MAIL_SMTP_VARIABLES | | 邮件发送参数 |
| MAIL_TO | | 接收邮件的地址 |
| MAIL_WHEN_SUCCESS | `TRUE` | 备份成功后发送邮件 |
| MAIL_WHEN_FAILURE | `TRUE` | 备份失败后发送邮件 |
对于 `MAIL_SMTP_VARIABLES`,你需要自行配置邮件发送参数。**我们会根据使用场景设置邮件主题,所以你不应该使用 `-s` 标志。**
```text
# 提供一个能正常使用的例子:
# For Zoho
-S smtp-use-starttls \
-S smtp=smtp://smtp.zoho.com:587 \
-S smtp-auth=login \
-S smtp-auth-user=<my-email-address> \
-S smtp-auth-password=<my-email-password> \
-S from=<my-email-address>
```
控制台有警告?查看 [issue #177](https://github.com/ttionya/vaultwarden-backup/issues/117#issuecomment-1691443179) 了解更多。
<br>
### 邮件发送测试
你可以使用下面的命令测试邮件发送功能。我们会增加 `-v` 标志以显示详细信息,你无需在 `MAIL_SMTP_VARIABLES` 中重复设置。
```shell
docker run --rm -it -e MAIL_SMTP_VARIABLES='<your smtp variables>' ttionya/vaultwarden-backup:latest mail <mail send to>
# Or
docker run --rm -it -e MAIL_SMTP_VARIABLES='<your smtp variables>' -e MAIL_TO='<mail send to>' ttionya/vaultwarden-backup:latest mail
```
<br>
### Ping
我们提供了在备份完成、开始、成功、失败时发送通知的功能。
@@ -477,6 +435,65 @@ docker run --rm -it \
### Mail
从 v1.19.0 开始,本工具使用 [`s-nail`](https://www.sdaoden.eu/code-nail.html) 代替 [`heirloom-mailx`](https://www.systutorials.com/docs/linux/man/1-heirloom-mailx/) 发送邮件。
请注意,`heirloom-mailx``s-nail` 的存根,它们大部分功能是兼容的。因此你可能不需要为这个改变修改任何环境变量。
| 环境变量 | 默认值 | 描述 |
| --- |--------|----------------------------------------|
| MAIL_SMTP_ENABLE | `FALSE` | 启用邮件发送功能 |
| MAIL_SMTP_VARIABLES | | 邮件发送参数 |
| MAIL_TO | | 接收邮件的地址 |
| MAIL_WHEN_SUCCESS | `TRUE` | 备份成功后发送邮件 |
| MAIL_WHEN_FAILURE | `TRUE` | 备份失败后发送邮件 |
| MAIL_FORCE_THREAD | `FALSE` | 尤其适用于邮件客户端在主题相同的情况下仍无法在对话视图中将相关邮件分组的情况 |
对于 `MAIL_SMTP_VARIABLES`,你需要自行配置邮件发送参数。**我们会根据使用场景设置邮件主题,所以你不应该使用 `-s` 标志。**
```text
# 提供一个能正常使用的例子:
# For Zoho
-S smtp-use-starttls \
-S smtp=smtp://smtp.zoho.com:587 \
-S smtp-auth=login \
-S smtp-auth-user=<my-email-address> \
-S smtp-auth-password=<my-email-password> \
-S from=<my-email-address>
```
控制台有警告?查看 [issue #177](https://github.com/ttionya/vaultwarden-backup/issues/117#issuecomment-1691443179) 了解更多。
对于 `MAIL_FORCE_THREAD`,在邮件客户端无法正确将邮件聚合到同一会话中时特别有用。它支持三种操作模式:
1. `FALSE`:默认电子邮件发送行为
2. `TRUE`:自动生成符合 RFC 的 Message-ID 以强制会话关联
3. `有效 Message-ID 字符串`:使用指定的 Message-ID 与现有会话关联。你可以在原始邮件内容的 Message-ID 字段中找到它
启用后,系统会自动添加所需的标头(`Message-ID``References``In-Reply-To`),以便邮件客户端适当地关联会话。
<br>
### 邮件发送测试
你可以使用下面的命令测试邮件发送功能。我们会增加 `-v` 标志以显示详细信息,你无需在 `MAIL_SMTP_VARIABLES` 中重复设置。
```shell
docker run --rm -it -e MAIL_SMTP_VARIABLES='<your smtp variables>' ttionya/vaultwarden-backup:latest mail <mail send to>
# Or
docker run --rm -it -e MAIL_SMTP_VARIABLES='<your smtp variables>' -e MAIL_TO='<mail send to>' ttionya/vaultwarden-backup:latest mail
```
<br>
## 环境变量注意事项
### 使用 `.env` 文件
@@ -528,10 +545,10 @@ MY_ENV="example1"
MY_ENV_FILE="/path/to/example2"
# 对于 3 (.env 文件)
MY_ENV_FILE: "/path/to/example3"
MY_ENV_FILE="/path/to/example3"
# 对于 4 (.env 文件)
MY_ENV: "example4"
MY_ENV="example4"
```
<br>
@@ -580,7 +597,7 @@ MY_ENV: "example4"
感谢 [JetBrains](https://www.jetbrains.com/) 提供的 OSS 许可证。
<a href="https://jb.gg/OpenSourceSupport" target="_blank"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" alt="JetBrains Logo (Main) logo" width="250"></a>
<a href="https://jb.gg/OpenSource" target="_blank"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" alt="JetBrains logo."></a>
<br>
@@ -17,10 +17,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
-
name: DockerHub Description
uses: peter-evans/dockerhub-description@v4
uses: peter-evans/dockerhub-description@v5
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -28,7 +28,7 @@ jobs:
enable-url-completion: true
-
name: DockerHub Description
uses: peter-evans/dockerhub-description@v4
uses: peter-evans/dockerhub-description@v5
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
+74 -48
View File
@@ -21,44 +21,51 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
-
name: Prepare
run: echo "TAG=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
-
name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Login to ghcr.io
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v6
name: Docker meta
id: meta
uses: docker/metadata-action@v6
with:
context: '.'
file: './Dockerfile'
platforms: 'linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7'
labels: |
org.opencontainers.image.title=vaultwarden-backup
org.opencontainers.image.description=Backup vaultwarden SQLite3/PostgreSQL/MySQL/MariaDB database by rclone
org.opencontainers.image.authors=ttionya
org.opencontainers.image.version=${{ env.VERSION }}
-
name: Build and push
uses: docker/bake-action@v7
env:
VERSION: ${{ env.VERSION }}
with:
source: .
files: |
./docker-bake.hcl
${{ steps.meta.outputs.bake-file-labels }}
targets: image-stable
push: true
tags: |
ttionya/vaultwarden-backup:latest
ttionya/vaultwarden-backup:${{ env.TAG }}
ttionya/bitwardenrs-backup:latest
ttionya/bitwardenrs-backup:${{ env.TAG }}
ghcr.io/ttionya/vaultwarden-backup:latest
ghcr.io/ttionya/vaultwarden-backup:${{ env.TAG }}
publish-beta:
name: Docker Publish Beta
@@ -70,32 +77,44 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
-
name: Prepare
run: echo "TAG=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
-
name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v6
name: Docker meta
id: meta
uses: docker/metadata-action@v6
with:
context: '.'
file: './Dockerfile'
platforms: 'linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7'
labels: |
org.opencontainers.image.title=vaultwarden-backup
org.opencontainers.image.description=Backup vaultwarden SQLite3/PostgreSQL/MySQL/MariaDB database by rclone
org.opencontainers.image.authors=ttionya
org.opencontainers.image.version=${{ env.VERSION }}
-
name: Build and push
uses: docker/bake-action@v7
env:
VERSION: ${{ env.VERSION }}
with:
source: .
files: |
./docker-bake.hcl
${{ steps.meta.outputs.bake-file-labels }}
targets: image-beta
push: true
tags: |
ttionya/vaultwarden-backup:${{ env.TAG }}
publish-schedule:
name: Docker Publish Schedule
@@ -114,45 +133,52 @@ jobs:
excludes: prerelease, draft
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: refs/tags/${{ steps.tag.outputs.release }}
-
name: Prepare
run: |
TAG=${{ steps.tag.outputs.release }}
echo "TAG=${TAG#v}" >> $GITHUB_ENV
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
-
name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Login to ghcr.io
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v6
name: Docker meta
id: meta
uses: docker/metadata-action@v6
with:
context: '.'
file: './Dockerfile'
platforms: 'linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7'
labels: |
org.opencontainers.image.title=vaultwarden-backup
org.opencontainers.image.description=Backup vaultwarden SQLite3/PostgreSQL/MySQL/MariaDB database by rclone
org.opencontainers.image.authors=ttionya
org.opencontainers.image.version=${{ env.VERSION }}
-
name: Build and push
uses: docker/bake-action@v7
env:
VERSION: ${{ env.VERSION }}
with:
source: .
files: |
./docker-bake.hcl
${{ steps.meta.outputs.bake-file-labels }}
targets: image-schedule
push: true
tags: |
ttionya/vaultwarden-backup:latest
ttionya/vaultwarden-backup:${{ env.TAG }}
ttionya/bitwardenrs-backup:latest
ttionya/bitwardenrs-backup:${{ env.TAG }}
ghcr.io/ttionya/vaultwarden-backup:latest
ghcr.io/ttionya/vaultwarden-backup:${{ env.TAG }}
+11 -13
View File
@@ -24,35 +24,33 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
with:
# network=host driver-opt needed to push to local registry
# https://docs.docker.com/build/ci/github-actions/named-contexts/#using-with-a-container-builder
driver-opts: network=host
-
name: Build base image
uses: docker/build-push-action@v6
uses: docker/bake-action@v7
with:
context: '.'
file: './Dockerfile'
platforms: 'linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7'
source: .
files: ./docker-bake.hcl
targets: image-test-base
push: true
tags: localhost:5000/base:dev
-
name: Build test image
uses: docker/build-push-action@v6
uses: docker/bake-action@v7
with:
context: '.'
file: './tests/Dockerfile'
build-contexts: base=docker-image://localhost:5000/base:dev
source: .
files: ./docker-bake.hcl
targets: image-test
load: true
tags: ttionya/vaultwarden-backup:test
-
name: Test
run: |
+2 -2
View File
@@ -18,10 +18,10 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
-
name: Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v3
with:
body: |
[CHANGELOG](https://github.com/ttionya/vaultwarden-backup/blob/master/CHANGELOG.md)
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
-
+68
View File
@@ -0,0 +1,68 @@
variable "VERSION" {
default = "latest"
}
variable "TEST_BASE_TAG" {
default = "localhost:5000/base:dev"
}
target "docker-metadata-action" {}
target "_common" {
inherits = ["docker-metadata-action"]
context = "."
dockerfile = "Dockerfile"
}
target "_common_multi_platforms" {
platforms = [
"linux/amd64",
"linux/arm64",
"linux/arm/v6",
"linux/arm/v7"
]
}
target "_common_tags" {
tags = [
"ttionya/vaultwarden-backup:latest",
"ttionya/vaultwarden-backup:${VERSION}",
"ttionya/bitwardenrs-backup:latest",
"ttionya/bitwardenrs-backup:${VERSION}",
"ghcr.io/ttionya/vaultwarden-backup:latest",
"ghcr.io/ttionya/vaultwarden-backup:${VERSION}"
]
}
target "image-stable" {
inherits = ["_common", "_common_multi_platforms", "_common_tags"]
}
target "image-schedule" {
inherits = ["image-stable"]
}
target "image-beta" {
inherits = ["_common", "_common_multi_platforms"]
tags = [
"ttionya/vaultwarden-backup:${VERSION}"
]
}
target "image-test-base" {
inherits = ["_common", "_common_multi_platforms"]
tags = [
"${TEST_BASE_TAG}"
]
}
target "image-test" {
inherits = ["_common"]
dockerfile = "./tests/Dockerfile"
contexts = {
base = "docker-image://${TEST_BASE_TAG}"
}
tags = [
"ttionya/vaultwarden-backup:test"
]
}
+1
View File
@@ -39,6 +39,7 @@ services:
# MAIL_TO: ''
# MAIL_WHEN_SUCCESS: 'TRUE'
# MAIL_WHEN_FAILURE: 'TRUE'
# MAIL_FORCE_THREAD: 'FALSE'
# TIMEZONE: 'UTC'
volumes:
- vaultwarden-data:/bitwarden/data/
+2
View File
@@ -4,6 +4,8 @@ Sometimes, it's necessary to manually trigger backup actions.
This can be useful when other programs are used to consistently schedule tasks or to verify that environment variables are properly configured.
If your container is already running (with the container name `vaultwarden_backup`) and you want to execute an adhoc backup you can do so with the command `docker exec vaultwarden_backup bash /app/backup.sh`.
<br>
@@ -40,6 +40,32 @@ Default: `vaultwarden`
MySQL(MariaDB) password, **required**.
#### MYSQL_SSL
Enable SSL for connection.
No default value is set; it uses the default provided by `mariadb-dump`, and starting from version `10.11`, the default is `TRUE`.
#### MYSQL_SSL_VERIFY_SERVER_CERT
Verify server's certificate.
No default value is set; it uses the default provided by `mariadb-dump`, and starting from version `11.4`, the default is `TRUE`.
If you encounter any TLS-related connection errors, you can try disabling it by setting values such as `0` or `FALSE`.
#### MYSQL_SSL_CA
The path to the CA certificate for TLS connection (optional).
#### MYSQL_SSL_CERT
The path to the client certificate for TLS connection (optional).
#### MYSQL_SSL_KEY
The path to the client key for TLS connection (optional).
<br>
+1 -3
View File
@@ -2,9 +2,7 @@
Now supports PostgreSQL backend.
~~Because upstream Rclone image is based on `alpine 3.16`(and `linux/arm/v6` platform is based on `alpine 3.15`), it **only supports PostgreSQL 14 and previous versions**, see [Alpine 3.16 Packages](https://pkgs.alpinelinux.org/packages?name=postgresql*-client&branch=v3.16) and [Alpine 3.15 Packages](https://pkgs.alpinelinux.org/packages?name=postgresql*-client&branch=v3.15).~~
We support PostgreSQL 16 and previous versions.
We support PostgreSQL 18 and previous versions.
If the `postgresql*-client` is not updated promptly, please create an issue to inform us.
+19 -2
View File
@@ -52,7 +52,24 @@ function backup_db_postgresql() {
function backup_db_mysql() {
color blue "backup vaultwarden mysql database"
mariadb-dump -h "${MYSQL_HOST}" -P "${MYSQL_PORT}" -u "${MYSQL_USERNAME}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" > "${BACKUP_FILE_DB_MYSQL}"
local EXTRA_OPTIONS=()
if [[ -n "${MYSQL_SSL}" ]]; then
EXTRA_OPTIONS+=("--ssl=\"${MYSQL_SSL}\"")
fi
if [[ -n "${MYSQL_SSL_VERIFY_SERVER_CERT}" ]]; then
EXTRA_OPTIONS+=("--ssl-verify-server-cert=\"${MYSQL_SSL_VERIFY_SERVER_CERT}\"")
fi
if [[ -n "${MYSQL_SSL_CA}" ]]; then
EXTRA_OPTIONS+=("--ssl-ca=\"${MYSQL_SSL_CA}\"")
fi
if [[ -n "${MYSQL_SSL_CERT}" ]]; then
EXTRA_OPTIONS+=("--ssl-cert=\"${MYSQL_SSL_CERT}\"")
fi
if [[ -n "${MYSQL_SSL_KEY}" ]]; then
EXTRA_OPTIONS+=("--ssl-key=\"${MYSQL_SSL_KEY}\"")
fi
eval "mariadb-dump -h \"${MYSQL_HOST}\" -P \"${MYSQL_PORT}\" -u \"${MYSQL_USERNAME}\" -p\"${MYSQL_PASSWORD}\" ${EXTRA_OPTIONS[@]} \"${MYSQL_DATABASE}\" > \"${BACKUP_FILE_DB_MYSQL}\""
if [[ $? != 0 ]]; then
color red "backup vaultwarden mysql database failed"
@@ -217,7 +234,7 @@ init_env
send_notification "start" "Start backup at $(date +"%Y-%m-%d %H:%M:%S %Z")"
check_rclone_connection
check_rclone_connection any
clear_dir
backup_init
+6 -4
View File
@@ -12,6 +12,7 @@ fi
# mail test
if [[ "$1" == "mail" ]]; then
export_env_file
init_env_display
init_env_mail
MAIL_SMTP_ENABLE="TRUE"
@@ -21,7 +22,7 @@ if [[ "$1" == "mail" ]]; then
MAIL_TO="$2"
fi
send_mail "vaultwarden Backup Test" "Your SMTP configuration looks correct."
send_mail "${DISPLAY_NAME} Backup Test" "Your SMTP configuration looks correct."
exit 0
fi
@@ -29,11 +30,12 @@ fi
# ping test
if [[ "$1" == "ping" ]]; then
export_env_file
init_env_display
init_env_ping
PING_DEBUG="TRUE"
send_ping "$2" "vaultwarden Backup Test" "Your PING configuration looks correct."
send_ping "$2" "${DISPLAY_NAME} Backup Test" "Your PING configuration looks correct."
exit 0
fi
@@ -60,7 +62,7 @@ function configure_cron() {
}
init_env
check_rclone_connection
check_rclone_connection all
configure_postgresql
configure_timezone
configure_cron
@@ -75,4 +77,4 @@ if [[ "$1" == "backup" ]]; then
fi
# foreground run crond
exec supercronic -passthrough-logs -quiet "${CRON_CONFIG_FILE}"
exec /usr/bin/supercronic -passthrough-logs -quiet "${CRON_CONFIG_FILE}"
+117 -16
View File
@@ -2,6 +2,8 @@
ENV_FILE="/.env"
CRON_CONFIG_FILE="${HOME}/crontabs"
MAIL_CONFIG_DIR="/config/mail"
MAIL_PARENT_MESSAGE_ID_FILE="${MAIL_CONFIG_DIR}/parent_message_id"
BACKUP_DIR="/bitwarden/backup"
RESTORE_DIR="/bitwarden/restore"
RESTORE_EXTRACT_DIR="/bitwarden/extract"
@@ -28,11 +30,19 @@ function color() {
########################################
# Check storage system connection success.
# Arguments:
# None
# success strategy (all / any)
########################################
function check_rclone_connection() {
# check configuration exist
rclone ${RCLONE_GLOBAL_FLAG} config show "${RCLONE_REMOTE_NAME}" > /dev/null 2>&1
# check flags validity
rclone ${RCLONE_GLOBAL_FLAG} version > /dev/null 2>&1
if [[ $? != 0 ]]; then
color red "illegal rclone global flags"
color blue "Please check https://rclone.org/flags/"
exit 1
fi
# check if the configuration exists
rclone ${RCLONE_GLOBAL_FLAG} config show 2>&1 | grep -F "[${RCLONE_REMOTE_NAME}]" > /dev/null
if [[ $? != 0 ]]; then
color red "rclone configuration information not found"
color blue "Please configure rclone first, check https://github.com/ttionya/vaultwarden-backup/blob/master/README.md#backup"
@@ -40,25 +50,40 @@ function check_rclone_connection() {
fi
# check connection
local HAS_ERROR="FALSE"
local ERROR_COUNT=0
for RCLONE_REMOTE_X in "${RCLONE_REMOTE_LIST[@]}"
do
rclone ${RCLONE_GLOBAL_FLAG} mkdir "${RCLONE_REMOTE_X}"
rclone ${RCLONE_GLOBAL_FLAG} lsd "${RCLONE_REMOTE_X}" > /dev/null
if [[ $? != 0 ]]; then
color red "storage system connection failure $(color yellow "[${RCLONE_REMOTE_X}]")"
color red "storage system connection may not be initialized, try initializing $(color yellow "[${RCLONE_REMOTE_X}]")"
HAS_ERROR="TRUE"
rclone ${RCLONE_GLOBAL_FLAG} mkdir "${RCLONE_REMOTE_X}"
if [[ $? != 0 ]]; then
color red "storage system connection failure $(color yellow "[${RCLONE_REMOTE_X}]")"
((ERROR_COUNT++))
fi
fi
done
if [[ "${HAS_ERROR}" == "TRUE" ]]; then
exit 1
if [[ "${ERROR_COUNT}" -gt 0 ]]; then
if [[ "$1" == "all" ]]; then
color red "storage system connection failure exists"
exit 1
elif [[ "$1" == "any" ]]; then
if [[ "${ERROR_COUNT}" -eq "${#RCLONE_REMOTE_LIST[@]}" ]]; then
color red "all storage system connections failed"
exit 1
else
color yellow "some storage system connections failed, but the backup will continue"
fi
fi
fi
}
########################################
# Check file is exist.
# Check if the file exists.
# Arguments:
# file
########################################
@@ -70,7 +95,7 @@ function check_file_exist() {
}
########################################
# Check directory is exist.
# Check if the directory exists.
# Arguments:
# directory
########################################
@@ -90,15 +115,40 @@ function check_dir_exist() {
# send mail result
########################################
function send_mail() {
local MAIL_VERBOSE_FLAG=""
local MAIL_TEMPLATE_FLAG=""
local MAIL_TEMPLATE=""
local MAIL_USED_MESSAGE_ID=""
# verbose
if [[ "${MAIL_DEBUG}" == "TRUE" ]]; then
local MAIL_VERBOSE="-v"
MAIL_VERBOSE_FLAG="-v"
fi
echo "$2" | mail ${MAIL_VERBOSE} -s "$1" ${MAIL_SMTP_VARIABLES} "${MAIL_TO}"
# template
if [[ "${MAIL_USE_THREAD}" == "TRUE" ]]; then
if [[ -n "${MAIL_PARENT_MESSAGE_ID}" ]]; then
MAIL_USED_MESSAGE_ID="${MAIL_PARENT_MESSAGE_ID}"
MAIL_TEMPLATE="References: ${MAIL_USED_MESSAGE_ID}\nIn-Reply-To: ${MAIL_USED_MESSAGE_ID}\n\n"
else
MAIL_USED_MESSAGE_ID="<$(date +%s%N).$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16).$(hostname)@vaultwarden.backup>"
MAIL_TEMPLATE="Message-ID: ${MAIL_USED_MESSAGE_ID}\n\n"
fi
fi
if [[ -n "${MAIL_TEMPLATE}" ]]; then
MAIL_TEMPLATE_FLAG="-t"
fi
echo -e "${MAIL_TEMPLATE}$2" | eval "mail ${MAIL_VERBOSE_FLAG} ${MAIL_TEMPLATE_FLAG} -s \"$1\" ${MAIL_SMTP_VARIABLES} \"${MAIL_TO}\""
if [[ $? != 0 ]]; then
color red "mail sending has failed"
else
color blue "mail has been sent successfully"
if [[ "${MAIL_USE_THREAD}" == "TRUE" && -z "${MAIL_PARENT_MESSAGE_ID}" ]]; then
mkdir -p "$(dirname "${MAIL_PARENT_MESSAGE_ID_FILE}")"
echo -n "${MAIL_USED_MESSAGE_ID}" > "${MAIL_PARENT_MESSAGE_ID_FILE}"
fi
fi
}
@@ -153,9 +203,9 @@ function send_ping() {
# notification content
########################################
function send_notification() {
local SUBJECT_START="vaultwarden Backup Start"
local SUBJECT_SUCCESS="vaultwarden Backup Success"
local SUBJECT_FAILURE="vaultwarden Backup Failed"
local SUBJECT_START="${DISPLAY_NAME} Backup Start"
local SUBJECT_SUCCESS="${DISPLAY_NAME} Backup Success"
local SUBJECT_FAILURE="${DISPLAY_NAME} Backup Failed"
case "$1" in
start)
@@ -291,6 +341,7 @@ function init_env() {
init_env_dir
init_env_db
init_env_display
init_env_ping
init_env_mail
@@ -401,8 +452,16 @@ function init_env() {
color yellow "MAIL_TO: ${MAIL_TO}"
color yellow "MAIL_WHEN_SUCCESS: ${MAIL_WHEN_SUCCESS}"
color yellow "MAIL_WHEN_FAILURE: ${MAIL_WHEN_FAILURE}"
if [[ "${MAIL_USE_THREAD}" == "TRUE" ]]; then
if [[ -n "${MAIL_PARENT_MESSAGE_ID}" ]]; then
color yellow "MAIL_PARENT_MESSAGE_ID: ${MAIL_PARENT_MESSAGE_ID}"
else
color yellow "MAIL_MESSAGE_ID: auto generate"
fi
fi
fi
color yellow "TIMEZONE: ${TIMEZONE}"
color yellow "DISPLAY_NAME: ${DISPLAY_NAME}"
color yellow "========================================"
}
@@ -482,11 +541,32 @@ function init_env_db() {
# MYSQL_PASSWORD
get_env MYSQL_PASSWORD
# MYSQL_SSL
get_env MYSQL_SSL
# MYSQL_SSL_VERIFY_SERVER_CERT
get_env MYSQL_SSL_VERIFY_SERVER_CERT
# MYSQL_SSL_CA
get_env MYSQL_SSL_CA
# MYSQL_SSL_CERT
get_env MYSQL_SSL_CERT
# MYSQL_SSL_KEY
get_env MYSQL_SSL_KEY
else # sqlite
DB_TYPE="SQLITE"
fi
}
function init_env_display() {
# DISPLAY_NAME
get_env DISPLAY_NAME
DISPLAY_NAME="${DISPLAY_NAME:-"vaultwarden"}"
}
function init_env_ping() {
# PING_URL
get_env PING_URL
@@ -551,4 +631,25 @@ function init_env_mail() {
else
MAIL_WHEN_FAILURE="TRUE"
fi
# MAIL_FORCE_THREAD
get_env MAIL_FORCE_THREAD
# 1. As long as MAIL_PARENT_MESSAGE_ID is valid (either specified or read from a file), MAIL_FORCE_THREAD must be set to TRUE.
# 2. As long as MAIL_FORCE_THREAD is set to TRUE, even if an invalid Message-ID is read from the file, it will be regenerated subsequently.
# 3. When MAIL_FORCE_THREAD is not set to TRUE, promptly clear the persistent files.
if [[ "${MAIL_FORCE_THREAD^^}" == "TRUE" ]]; then
MAIL_USE_THREAD="TRUE"
if [[ -f "${MAIL_PARENT_MESSAGE_ID_FILE}" && -s "${MAIL_PARENT_MESSAGE_ID_FILE}" ]]; then
MAIL_PARENT_MESSAGE_ID="$(cat "${MAIL_PARENT_MESSAGE_ID_FILE}")"
fi
else
MAIL_PARENT_MESSAGE_ID="${MAIL_FORCE_THREAD}"
MAIL_USE_THREAD="FALSE"
rm -rf "${MAIL_CONFIG_DIR}"
fi
if [[ "${MAIL_PARENT_MESSAGE_ID}" =~ ^\<.*\@.+\>$ ]]; then
MAIL_USE_THREAD="TRUE"
else
MAIL_PARENT_MESSAGE_ID=""
fi
}
+18 -1
View File
@@ -90,7 +90,24 @@ function restore_db_postgresql() {
function restore_db_mysql() {
color blue "restore vaultwarden mysql database"
mariadb -h "${MYSQL_HOST}" -P "${MYSQL_PORT}" -u "${MYSQL_USERNAME}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" < "${RESTORE_FILE_DB}"
local EXTRA_OPTIONS=()
if [[ -n "${MYSQL_SSL}" ]]; then
EXTRA_OPTIONS+=("--ssl=\"${MYSQL_SSL}\"")
fi
if [[ -n "${MYSQL_SSL_VERIFY_SERVER_CERT}" ]]; then
EXTRA_OPTIONS+=("--ssl-verify-server-cert=\"${MYSQL_SSL_VERIFY_SERVER_CERT}\"")
fi
if [[ -n "${MYSQL_SSL_CA}" ]]; then
EXTRA_OPTIONS+=("--ssl-ca=\"${MYSQL_SSL_CA}\"")
fi
if [[ -n "${MYSQL_SSL_CERT}" ]]; then
EXTRA_OPTIONS+=("--ssl-cert=\"${MYSQL_SSL_CERT}\"")
fi
if [[ -n "${MYSQL_SSL_KEY}" ]]; then
EXTRA_OPTIONS+=("--ssl-key=\"${MYSQL_SSL_KEY}\"")
fi
eval "mariadb -h \"${MYSQL_HOST}\" -P \"${MYSQL_PORT}\" -u \"${MYSQL_USERNAME}\" -p\"${MYSQL_PASSWORD}\" --show-warnings ${EXTRA_OPTIONS[@]} \"${MYSQL_DATABASE}\" < \"${RESTORE_FILE_DB}\""
if [[ $? == 0 ]]; then
color green "restore vaultwarden mysql database successful"
+4
View File
@@ -0,0 +1,4 @@
# Encrypted rclone configuration File (ttionya)
RCLONE_ENCRYPT_V0:
l3mwqE8IiDshJArOYQLMlsen3b/oGL2mT87k29sB0nnLch1gH8aV6oJYh5IrUvKtY8FeCKaNq0cENcYR5V0W7IcHqKFYl1lyo7nG
+12
View File
@@ -5,8 +5,10 @@ DOCKER_IMAGE="ttionya/vaultwarden-backup:test"
ERROR_NUM=0
DATA_DIR="$(pwd)/tests/fixtures/source/bitwarden/data"
CONFIG_DIR="config"
OUTPUT_DIR="output"
EXTRACT_DIR="extract"
TEMP_DIR="tmp"
REMOTE_DIR="/${OUTPUT_DIR}"
########################################
@@ -76,19 +78,29 @@ function check_files_same_in_folders() {
# test result
########################################
function test_result() {
local SEP="================================================================================"
if [[ "$2" == "0" ]]; then
color green "Test case \"$1\" passed"
color none "${SEP}${SEP}"
return
fi
((ERROR_NUM++))
color red "Test case \"$1\" failed"
color none "${SEP}${SEP}"
}
. tests/units/env-priority/test.sh
. tests/units/check-rclone-config-exists/test.sh
. tests/units/check-rclone-flags-valid/test.sh
. tests/units/check-rclone-connection-initializing/test.sh
. tests/units/check-encrypted-rclone-config/test.sh
. tests/units/backup-zip-file/test.sh
. tests/units/backup-7z-file/test.sh
. tests/units/backup-unpackage/test.sh
. tests/units/backup-cron/test.sh
if [[ "${ERROR_NUM}" == "0" ]]; then
color green "All tests passed"
+10
View File
@@ -48,8 +48,18 @@ function test() {
fi
}
function cleanup() {
sudo rm -rf "${TEST_OUTPUT_DIR}" "${TEST_EXTRACT_DIR}"
unset TEST_OUTPUT_DIR
unset TEST_EXTRACT_DIR
unset PASSWORD
unset BACKUP_FILE
}
prepare
start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
+70
View File
@@ -0,0 +1,70 @@
#!/bin/bash
TEST_NAME="backup-cron"
TEST_CONTAINER_NAME="${TEST_NAME}"
TEST_OUTPUT_DIR="$(pwd)/${OUTPUT_DIR}/${TEST_NAME}"
PASSWORD="faedea12-7f9e-4d84-983f-d049d9b82a36"
BACKUP_FILE="${TEST_OUTPUT_DIR}/backup.test.zip"
FAILED_NUM=0
color yellow "Starting test case \"${TEST_NAME}\""
function prepare() {
mkdir -p "${TEST_OUTPUT_DIR}"
}
function start() {
docker run --rm -d \
--name "${TEST_CONTAINER_NAME}" \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
-e "RCLONE_REMOTE_DIR=${REMOTE_DIR}" \
-e "ZIP_PASSWORD=${PASSWORD}" \
-e "BACKUP_FILE_SUFFIX=test" \
-e "CRON=* * * * *" \
"${DOCKER_IMAGE}"
}
function test() {
color blue "Testing..."
local TIMER=0
local SUCCESS=FALSE
# wait 120s
while [[ "${TIMER}" -lt 120 ]]; do
if [[ -f "${BACKUP_FILE}" && -s "${BACKUP_FILE}" ]]; then
SUCCESS=TRUE
break
fi
sleep 1
((TIMER++))
done
ls -l "${BACKUP_FILE}"
if [[ "${SUCCESS}" == "FALSE" ]]; then
((FAILED_NUM++))
fi
}
function cleanup() {
# stop the container
docker stop "${TEST_CONTAINER_NAME}"
sudo rm -rf "${TEST_OUTPUT_DIR}"
unset TEST_CONTAINER_NAME
unset TEST_OUTPUT_DIR
unset PASSWORD
unset BACKUP_FILE
}
prepare
start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
+8
View File
@@ -45,8 +45,16 @@ function test() {
fi
}
function cleanup() {
sudo rm -rf "${TEST_OUTPUT_DIR}" "${TEST_EXTRACT_DIR}"
unset TEST_OUTPUT_DIR
unset TEST_EXTRACT_DIR
}
prepare
start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
+10
View File
@@ -47,8 +47,18 @@ function test() {
fi
}
function cleanup() {
sudo rm -rf "${TEST_OUTPUT_DIR}" "${TEST_EXTRACT_DIR}"
unset TEST_OUTPUT_DIR
unset TEST_EXTRACT_DIR
unset PASSWORD
unset BACKUP_FILE
}
prepare
start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
@@ -0,0 +1,66 @@
#!/bin/bash
TEST_NAME="check-encrypted-rclone-config"
TEST_OUTPUT_DIR="$(pwd)/${OUTPUT_DIR}/${TEST_NAME}"
TEST_EXTRACT_DIR="$(pwd)/${EXTRACT_DIR}/${TEST_NAME}"
PASSWORD="32d22daa-4e38-4c4c-8eeb-caf954d2259c"
BACKUP_FILE="${TEST_OUTPUT_DIR}/backup.test.zip"
FAILED_NUM=0
color yellow "Starting test case \"${TEST_NAME}\""
function prepare() {
mkdir -p "${TEST_OUTPUT_DIR}" "${TEST_EXTRACT_DIR}"
}
function start() {
docker run --rm \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
-e "RCLONE_REMOTE_DIR=${REMOTE_DIR}" \
-e "RCLONE_GLOBAL_FLAG=--config /config/rclone/rclone.enc.conf" \
-e "RCLONE_CONFIG_PASS=ttionya" \
-e "ZIP_PASSWORD=${PASSWORD}" \
-e "BACKUP_FILE_SUFFIX=test" \
"${DOCKER_IMAGE}" \
backup
}
function test() {
color blue "Testing..."
ls -l "${BACKUP_FILE}"
7z l -p"${PASSWORD}" "${BACKUP_FILE}"
docker run --rm \
--mount "type=bind,source=${TEST_EXTRACT_DIR},target=/bitwarden/data/" \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=/bitwarden/restore/" \
"${DOCKER_IMAGE}" \
restore \
-f \
-p "${PASSWORD}" \
--zip-file "$(basename "${BACKUP_FILE}")"
check_files_same_in_folders "${DATA_DIR}" "${TEST_EXTRACT_DIR}"
if [[ $? != 0 ]]; then
((FAILED_NUM++))
fi
}
function cleanup() {
sudo rm -rf "${TEST_OUTPUT_DIR}" "${TEST_EXTRACT_DIR}"
unset TEST_OUTPUT_DIR
unset TEST_EXTRACT_DIR
unset PASSWORD
unset BACKUP_FILE
}
prepare
start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
@@ -0,0 +1,56 @@
#!/bin/bash
# During Rclone connection verification, the configuration is considered complete
# by checking for the presence of `RCLONE_REMOTE_NAME` in the configuration file.
#
# This test case ensures the verification method works by triggering the expected error message.
TEST_NAME="check-rclone-config-exits"
TEST_OUTPUT_DIR="$(pwd)/${OUTPUT_DIR}/${TEST_NAME}"
TEST_CONFIG_DIR="$(pwd)/${CONFIG_DIR}/${TEST_NAME}"
PASSWORD="231454f1-594c-45e2-8810-3ac917ebcf70"
FAILED_NUM=0
color yellow "Starting test case \"${TEST_NAME}\""
function prepare() {
mkdir -p "${TEST_OUTPUT_DIR}" "${TEST_CONFIG_DIR}"
}
# function start() {
# }
function test() {
color blue "Testing..."
FOUND_MESSAGE_COUNT=$(docker run --rm \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
--mount "type=bind,source=${TEST_CONFIG_DIR},target=/config" \
-e "RCLONE_REMOTE_DIR=${REMOTE_DIR}" \
-e "ZIP_PASSWORD=${PASSWORD}" \
-e "BACKUP_FILE_SUFFIX=test" \
"${DOCKER_IMAGE}" \
backup | grep -c "rclone configuration information not found")
if [[ "${FOUND_MESSAGE_COUNT}" -ne 1 ]]; then
((FAILED_NUM++))
fi
}
function cleanup() {
sudo rm -rf "${TEST_OUTPUT_DIR}" "${TEST_CONFIG_DIR}"
unset TEST_OUTPUT_DIR
unset TEST_CONFIG_DIR
unset PASSWORD
unset FOUND_MESSAGE_COUNT
}
prepare
# start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
@@ -0,0 +1,76 @@
#!/bin/bash
# When verifying the Rclone connection, the previous method ensured
# the remote directory existed by creating it (mkdir), which requires special permissions on S3.
# It has been changed to attempt listing the remote directory (lsd) to avoid this issue.
# If listing the directory fails, the directory is considered non-existent and will be created.
# See issue https://github.com/ttionya/vaultwarden-backup/issues/199 for details.
#
# This test case verifies that the remote directory can be created correctly without affecting the backup operation.
TEST_NAME="check-rclone-connection-initializing"
TEST_OUTPUT_DIR="$(pwd)/${OUTPUT_DIR}/${TEST_NAME}"
TEST_EXTRACT_DIR="$(pwd)/${EXTRACT_DIR}/${TEST_NAME}"
TEST_DIR="/folder1/folder2/folder3"
TEST_REMOTE_DIR="${REMOTE_DIR}${TEST_DIR}"
PASSWORD="9eeef525-24e9-496b-9e32-990211dce6eb"
BACKUP_FILE="${TEST_OUTPUT_DIR}${TEST_DIR}/backup.test.zip"
FAILED_NUM=0
color yellow "Starting test case \"${TEST_NAME}\""
function prepare() {
mkdir -p "${TEST_OUTPUT_DIR}" "${TEST_EXTRACT_DIR}"
}
function start() {
docker run --rm \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
-e "RCLONE_REMOTE_DIR=${TEST_REMOTE_DIR}" \
-e "ZIP_PASSWORD=${PASSWORD}" \
-e "BACKUP_FILE_SUFFIX=test" \
"${DOCKER_IMAGE}" \
backup
}
function test() {
color blue "Testing..."
ls -l "${BACKUP_FILE}"
7z l -p"${PASSWORD}" "${BACKUP_FILE}"
docker run --rm \
--mount "type=bind,source=${TEST_EXTRACT_DIR},target=/bitwarden/data/" \
--mount "type=bind,source=$(dirname "${BACKUP_FILE}"),target=/bitwarden/restore/" \
"${DOCKER_IMAGE}" \
restore \
-f \
-p "${PASSWORD}" \
--zip-file "$(basename "${BACKUP_FILE}")"
check_files_same_in_folders "${DATA_DIR}" "${TEST_EXTRACT_DIR}"
if [[ $? != 0 ]]; then
((FAILED_NUM++))
fi
}
function cleanup() {
sudo rm -rf "${TEST_OUTPUT_DIR}" "${TEST_EXTRACT_DIR}"
unset TEST_OUTPUT_DIR
unset TEST_EXTRACT_DIR
unset TEST_DIR
unset TEST_REMOTE_DIR
unset PASSWORD
unset BACKUP_FILE
}
prepare
start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
@@ -0,0 +1,53 @@
#!/bin/bash
# Using non-existent flags with Rclone will throw an exception and exit.
#
# This test case ensures the verification method works correctly by triggering the error message.
TEST_NAME="check-rclone-flags-valid"
TEST_OUTPUT_DIR="$(pwd)/${OUTPUT_DIR}/${TEST_NAME}"
PASSWORD="43ef5fec-292d-4f9a-ab97-34f622deb462"
FAILED_NUM=0
color yellow "Starting test case \"${TEST_NAME}\""
function prepare() {
mkdir -p "${TEST_OUTPUT_DIR}"
}
# function start() {
# }
function test() {
color blue "Testing..."
FOUND_MESSAGE_COUNT=$(docker run --rm \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
-e "RCLONE_REMOTE_DIR=${REMOTE_DIR}" \
-e "RCLONE_GLOBAL_FLAG=-v --non-existent" \
-e "ZIP_PASSWORD=${PASSWORD}" \
-e "BACKUP_FILE_SUFFIX=test" \
"${DOCKER_IMAGE}" \
backup | grep -c "illegal rclone global flags")
if [[ "${FOUND_MESSAGE_COUNT}" -ne 1 ]]; then
((FAILED_NUM++))
fi
}
function cleanup() {
sudo rm -rf "${TEST_OUTPUT_DIR}"
unset TEST_OUTPUT_DIR
unset PASSWORD
unset FOUND_MESSAGE_COUNT
}
prepare
# start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
+137
View File
@@ -0,0 +1,137 @@
#!/bin/bash
# The tool can set environment variables in four ways.
# This test case tests the priority by setting different passwords for the environment variable `ZIP_PASSWORD`.
TEST_NAME="env-priority"
TEST_OUTPUT_DIR="$(pwd)/${OUTPUT_DIR}/${TEST_NAME}"
TEST_TEMP_DIR="$(pwd)/${TEMP_DIR}/${TEST_NAME}"
PASSWORD1="32aeec18-3bce-43af-b41d-7be04b0f7810" # For 1
PASSWORD2="ce3cbc42-186b-4d1b-a1a9-3f10f0ec59c7" # For 2
PASSWORD3="0e0fdbc1-5b2f-44db-ac7d-f0a8764992a7" # For 3
PASSWORD4="0ddd9b27-ca9b-4912-b6fb-76569ec5cac1" # For 4
PASSWORD2_FILE="${TEST_TEMP_DIR}/password2"
PASSWORD3_FILE="${TEST_TEMP_DIR}/password3"
BACKUP_FILE1="${TEST_OUTPUT_DIR}/backup.test1.zip"
BACKUP_FILE2="${TEST_OUTPUT_DIR}/backup.test2.zip"
BACKUP_FILE3="${TEST_OUTPUT_DIR}/backup.test3.zip"
BACKUP_FILE4="${TEST_OUTPUT_DIR}/backup.test4.zip"
ENV_FILE1="${TEST_TEMP_DIR}/.env1"
ENV_FILE4="${TEST_TEMP_DIR}/.env4"
FAILED_NUM=0
color yellow "Starting test case \"${TEST_NAME}\""
function prepare() {
mkdir -p "${TEST_OUTPUT_DIR}" "${TEST_TEMP_DIR}"
echo "${PASSWORD2}" > "${PASSWORD2_FILE}"
echo "${PASSWORD3}" > "${PASSWORD3_FILE}"
cat > "${ENV_FILE1}" << EOF
ZIP_PASSWORD_FILE="/password3"
ZIP_PASSWORD="${PASSWORD4}"
EOF
cat > "${ENV_FILE4}" << EOF
ZIP_PASSWORD="${PASSWORD4}"
EOF
}
function start() {
docker run --rm \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
--mount "type=bind,source=${PASSWORD2_FILE},target=/password2" \
--mount "type=bind,source=${PASSWORD3_FILE},target=/password3" \
--mount "type=bind,source=${ENV_FILE1},target=/.env" \
-e "RCLONE_REMOTE_DIR=${REMOTE_DIR}" \
-e "ZIP_PASSWORD=${PASSWORD1}" \
-e "ZIP_PASSWORD_FILE=/password2" \
-e "BACKUP_FILE_SUFFIX=test1" \
"${DOCKER_IMAGE}" \
backup
docker run --rm \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
--mount "type=bind,source=${PASSWORD2_FILE},target=/password2" \
--mount "type=bind,source=${PASSWORD3_FILE},target=/password3" \
--mount "type=bind,source=${ENV_FILE1},target=/.env" \
-e "RCLONE_REMOTE_DIR=${REMOTE_DIR}" \
-e "ZIP_PASSWORD_FILE=/password2" \
-e "BACKUP_FILE_SUFFIX=test2" \
"${DOCKER_IMAGE}" \
backup
docker run --rm \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
--mount "type=bind,source=${PASSWORD2_FILE},target=/password2" \
--mount "type=bind,source=${PASSWORD3_FILE},target=/password3" \
--mount "type=bind,source=${ENV_FILE1},target=/.env" \
-e "RCLONE_REMOTE_DIR=${REMOTE_DIR}" \
-e "BACKUP_FILE_SUFFIX=test3" \
"${DOCKER_IMAGE}" \
backup
docker run --rm \
--mount "type=bind,source=${TEST_OUTPUT_DIR},target=${REMOTE_DIR}" \
--mount "type=bind,source=${PASSWORD2_FILE},target=/password2" \
--mount "type=bind,source=${PASSWORD3_FILE},target=/password3" \
--mount "type=bind,source=${ENV_FILE4},target=/.env" \
-e "RCLONE_REMOTE_DIR=${REMOTE_DIR}" \
-e "BACKUP_FILE_SUFFIX=test4" \
"${DOCKER_IMAGE}" \
backup
}
function test() {
color blue "Testing..."
ls -l "${TEST_OUTPUT_DIR}"
7z t -p"${PASSWORD1}" "${BACKUP_FILE1}"
if [[ $? != 0 ]]; then
((FAILED_NUM++))
fi
7z t -p"${PASSWORD2}" "${BACKUP_FILE2}"
if [[ $? != 0 ]]; then
((FAILED_NUM++))
fi
7z t -p"${PASSWORD3}" "${BACKUP_FILE3}"
if [[ $? != 0 ]]; then
((FAILED_NUM++))
fi
7z t -p"${PASSWORD4}" "${BACKUP_FILE4}"
if [[ $? != 0 ]]; then
((FAILED_NUM++))
fi
}
function cleanup() {
sudo rm -rf "${TEST_OUTPUT_DIR}" "${TEST_TEMP_DIR}"
unset TEST_OUTPUT_DIR
unset TEST_TEMP_DIR
unset PASSWORD1
unset PASSWORD2
unset PASSWORD3
unset PASSWORD4
unset PASSWORD2_FILE
unset PASSWORD3_FILE
unset BACKUP_FILE1
unset BACKUP_FILE2
unset BACKUP_FILE3
unset BACKUP_FILE4
unset ENV_FILE1
unset ENV_FILE4
}
prepare
start
test
cleanup
test_result "${TEST_NAME}" "${FAILED_NUM}"
+1 -1
View File
@@ -1 +1 @@
v1.21.2
v1.26.8