Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/SavageSoftware/portainer-backup

Portainer Backup Utility
https://github.com/SavageSoftware/portainer-backup

backup backup-script docker docker-compose docker-container docker-image portainer portainer-api portainer-ce

Last synced: 11 days ago
JSON representation

Portainer Backup Utility

Lists

README

        

[![Docker](https://img.shields.io/docker/v/savagesoftware/portainer-backup/latest?color=darkgreen&logo=docker&label=DockerHub%20Latest%20Image)](https://hub.docker.com/repository/docker/savagesoftware/portainer-backup/)
[![NPM](https://img.shields.io/npm/v/portainer-backup?color=darkgreen&logo=npm&label=NPM%20Registry)](https://www.npmjs.com/package/portainer-backup)
[![GitHub package.json version](https://img.shields.io/github/package-json/v/savagesoftware/portainer-backup?color=darkgreen&label=GitHub%20Source&logo=github)](https://github.com/SavageSoftware/portainer-backup)
[![node-current](https://img.shields.io/node/v/portainer-backup)](https://www.npmjs.com/package/portainer-backup)
[![portainer](https://img.shields.io/badge/Portainer->=v2.11.0-darkgreen)](https://www.portainer.io/)

# Portainer Backup

(Developed with ♥ by SavageSoftware, LLC.)

---

## Overview

A utility for scripting or scheduling Portainer backups. This utility can backup the entire Portainer database, optionally protect the archive file with a password and can additionally backup the `docker-compose` files for stacks created in the Portainer web interface.

![SCREENSHOT](https://github.com/SavageSoftware/portainer-backup/raw/master/assets/screenshot.jpg)

| Resources | URL |
| --- | --- |
| DockerHub Image | https://hub.docker.com/repository/docker/savagesoftware/portainer-backup/ |
| NPM Package Registry | https://www.npmjs.com/package/portainer-backup |

---

## Table of Contents

* [Overview](#overview)
* [TL;DR](#tldr)
* [Prerequisites](#prerequisites)
* [Installation](#installation)
* [Supported Commands & Operations](#supported-commands--operations)
* [Backup](#backup)
* [Test](#test)
* [Schedule](#schedule)
* [Info](#info)
* [Stacks](#stacks)
* [Restore](#restore)
* [Return Value](#return-value)
* [Command Line Options & Environment Variables](#command-line-options--environment-variables)
* [Schedule Expression](#schedule-expression)
* [Filename & Directory Date/Time Substituions](#filename--directory-datetime-substituions)
* [Supported Presets](#supported-presets)
* [Supported Tokens](#supported-tokens)
* [Command Line Help](#command-line-help)
* [Docker Compose](#docker-compose)

---

## TL;DR

**NodeJS & NPM**

Command to install **portainer-backup** using node's **NPM** command:

```shell
npm install --global portainer-backup
```

Command to launch **portainer-backup** after installing with NPM to perform a **backup** of your portainer server:

```shell
portainer-backup \
backup \
--url "http://portainer:9000" \
--token "PORTAINER_ACCESS_TOKEN" \
--directory $PWD/backup
```

**NPX**

Command to install & launch **portainer-backup** using node's [NPX](https://nodejs.dev/learn/the-npx-nodejs-package-runner) command to perform a **backup** of your portainer server:

```shell
npx portainer-backup \
backup \
--url "http://portainer:9000" \
--token "PORTAINER_ACCESS_TOKEN" \
--directory $PWD/backup
```

**DOCKER**

Command to launch **portainer-backup** using a Docker container to perform a **backup** of your portainer server:

```shell
docker run -it --rm \
--name portainer-backup \
--volume $PWD/backup:/backup \
--env PORTAINER_BACKUP_URL="http://portainer:9000" \
--env PORTAINER_BACKUP_TOKEN="YOUR_ACCESS_TOKEN" \
savagesoftware/portainer-backup:latest \
backup
```

Supported Docker platforms:
* `linux/amd64` (Intel/AMD x64)
* `linux/arm64` (ARMv8)
* `linux/arm` (ARMv7)

---

## Prerequisites

**Portainer-backup** requires the following prerequisites:

| Prerequisite | Version | Link |
| ------------ | ------- | -------- |
| NodeJS | v16 (LTS) | https://nodejs.org |
| Portainer | v2.11.0 (and newer) | https://www.portainer.io |
| Portainer Access Token | N/A | https://docs.portainer.io/v/ce-2.11/api/access |

[![node-current](https://img.shields.io/node/v/portainer-backup)](https://www.npmjs.com/package/portainer-backup)
[![portainer](https://img.shields.io/badge/Portainer-v2.11.0-darkgreen)](https://www.portainer.io/)

This utility has only been tested on Portainer **v2.11.0** and later.

> **NOTE:** If attempting to use with an older version of Portainer this utility will exit with an error message. While it is untested, you can use the `--ignore-version` option to bypass the version validation/enforcement.

You will need to obtain a [Portiner Access Token](https://docs.portainer.io/v/ce-2.11/api/access) from your Portainer server from an adminstrative user account.

---

## Installation

Command to install **portainer-backup** using node's **NPM** command:

```shell
npm install --global portainer-backup
```

[![NPM](https://nodei.co/npm/portainer-backup.png?downloads=true&downloadRank=false&stars=false)](https://www.npmjs.com/package/portainer-backup)

---

## Supported Commands & Operations

This utility requires a single command to execute one of the built in operations.

| Command | Description |
| ---------- | ----------- |
| [`backup`](#backup) | Backup portainer data archive |
| [`schedule`](#schedule) | Run scheduled portainer backups |
| [`stacks`](#stacks) | Backup portainer stacks |
| [`test`](#test) | Test backup (no files are saved) |
| [`info`](#info) | Get portainer server info |
| [`restore`](#restore) | Restore portainer data |

> **NOTE:** The `restore` command is not currently implemented due to issues with the Portainer API.

### Backup

The **backup** operation will perform a single backup of the Portainer data from the specified server. This backup file will be TAR.GZ archive and can optionally be protected with a password (`--password`). The process will terminate immedately after the **backup** operation is complete.

The following command will perform a **backup** of the Portainer data.
```shell
portainer-backup \
backup \
--url "http://portainer:9000" \
--token "PORTAINER_ACCESS_TOKEN" \
--directory $PWD/backup \
--overwrite
```

The following docker command will perform a **backup** of the Portainer data.
```shell
docker run -it --rm \
--name portainer-backup \
--volume $PWD/backup:/backup \
--env TZ="America/New_York" \
--env PORTAINER_BACKUP_URL="http://portainer:9000" \
--env PORTAINER_BACKUP_TOKEN="PORTAINER_ACCESS_TOKEN" \
--env PORTAINER_BACKUP_OVERWRITE=true \
--env PORTAINER_BACKUP_DIRECTORY=/backup \
savagesoftware/portainer-backup:latest \
backup
```

### Test

The **test** operation will perform a single backup of the Portainer data from the specified server. With the **test** operation, no data will be saved on the filesystem. The **test** operation is the same as using the `--dryrun` option. The process will terminate immedately after the **test** operation is complete.

The following command will perform a **test** of the Portainer data.
```shell
portainer-backup \
test \
--url "http://portainer:9000" \
--token "PORTAINER_ACCESS_TOKEN" \
--directory $PWD/backup
```

The following docker command will perform a **test** of the Portainer data.
```shell
docker run -it --rm \
--name portainer-backup \
--volume $PWD/backup:/backup \
--env TZ="America/New_York" \
--env PORTAINER_BACKUP_URL="http://portainer:9000" \
--env PORTAINER_BACKUP_TOKEN="PORTAINER_ACCESS_TOKEN" \
--env PORTAINER_BACKUP_DIRECTORY=/backup \
savagesoftware/portainer-backup:latest \
test
```

### Schedule

The **schedule** operation will perform continious scheduled backups of the Portainer data from the specified server. The `--schedule` option or `PORTAINER_BACKUP_SCHEDULE` environment variable takes a cron-like string expression to define the backup schedule. The process will run continiously unless a validation step fails immediately after startup.

The following command will perform a **test** of the Portainer data.
```shell
portainer-backup \
schedule \
--url "http://portainer:9000" \
--token "PORTAINER_ACCESS_TOKEN" \
--directory $PWD/backup \
--overwrite \
--schedule "0 0 0 * * *"
```

The following docker command will perform a **schedule** of the Portainer data.
```shell
docker run -it --rm \
--name portainer-backup \
--volume $PWD/backup:/backup \
--env TZ="America/New_York" \
--env PORTAINER_BACKUP_URL="http://portainer:9000" \
--env PORTAINER_BACKUP_TOKEN="PORTAINER_ACCESS_TOKEN" \
--env PORTAINER_BACKUP_OVERWRITE=true \
--env PORTAINER_BACKUP_DIRECTORY=/backup \
--env PORTAINER_BACKUP_SCHEDULE="0 0 0 * * *" \
savagesoftware/portainer-backup:latest \
schedule
```

### Info

The **info** operation will perform an information request to the specified Portainer server. The process will terminate immedately after the **info** operation is complete.

The following command will perform a **info** from the Portainer server.
```shell
portainer-backup info --url "http://portainer:9000"
```

The following docker command will perform a **info** request from the Portainer data.
```shell
docker run -it --rm \
--name portainer-backup \
--env PORTAINER_BACKUP_URL="http://portainer:9000" \
savagesoftware/portainer-backup:latest \
info
```

### Stacks

The **stacks** operation will perform a single backup of the Portainer stacks `docker-compose` data from the specified server. This operation does not backup the Portainer database/data files, only the stacks. Alternatively you can include stacks backups in the **backup** operation using the `--stacks` option. The process will terminate immedately after the **stacks** operation is complete.

The following command will perform a **stacks** of the Portainer data.
```shell
portainer-backup \
backup \
--url "http://portainer:9000" \
--token "PORTAINER_ACCESS_TOKEN" \
--directory $PWD/backup \
--stacks
```

The following docker command will perform a **stacks** of the Portainer data.
```shell
docker run -it --rm \
--name portainer-backup \
--volume $PWD/backup:/backup \
--env TZ="America/New_York" \
--env PORTAINER_BACKUP_URL="http://portainer:9000" \
--env PORTAINER_BACKUP_TOKEN="PORTAINER_ACCESS_TOKEN" \
--env PORTAINER_BACKUP_OVERWRITE=true \
--env PORTAINER_BACKUP_DIRECTORY=/backup \
savagesoftware/portainer-backup:latest \
stacks
```

### Restore

The **restore** operation is not implemented at this time. We encountered trouble getting the Portainer **restore** API (https://app.swaggerhub.com/apis/portainer/portainer-ce/2.11.1#/backup/Restore) to work properly and are investigating this issue further.

---

## Return Value

**Portainer-backup** will return a numeric value after the process exits.

| Value | Description |
| ----- | ----------- |
| 0 | Utility executed command successfully |
| 1 | Utility encountered an error and failed |

---

## Command Line Options & Environment Variables

**Portainer-backup** supports both command line arguments and environment variables for all configuration options.

| Option | Environment Variable | Type | Description |
| ----------- | -------------------- | ---- | ----------- |
| `-t`, `--token` | `PORTAINER_BACKUP_TOKEN` | string | Portainer access token |
| `-u`, `--url` | `PORTAINER_BACKUP_URL` | string | Portainer base url |
| `-Z`, `--ignore-version` | `PORTAINER_BACKUP_IGNORE_VERSION` | true\|false | Bypass portainer version check/enforcement |
| `-d`, `--directory`, `--dir` | `PORTAINER_BACKUP_DIRECTORY` | string | Backup directory/path |
| `-f`, `--filename` | `PORTAINER_BACKUP_FILENAME` | string | Backup filename |
| `-p`, `--password`, `--pw` | `PORTAINER_BACKUP_PASSWORD` | string | Backup archive password |
| `-M`, `--mkdir`, `--make-directory` | `PORTAINER_BACKUP_MKDIR` | true\|false | Create backup directory path |
| `-o`, `--overwrite` | `PORTAINER_BACKUP_OVERWRITE` | true\|false | Overwrite existing files |
| `-s`, `--schedule`, `--sch` | `PORTAINER_BACKUP_SCHEDULE` | string | Cron expression for scheduled backups |
| `-i`, `--include-stacks`, `--stacks`| `PORTAINER_BACKUP_STACKS` | true\|false | Include stack files in backup |
| `-q`, `--quiet` | `PORTAINER_BACKUP_QUIET` | true\|false | Do not display any console output |
| `-D`, `--dryrun` | `PORTAINER_BACKUP_DRYRUN` | true\|false | Execute command task without persisting any data |
| `-X`, `--debug` | `PORTAINER_BACKUP_DEBUG` | true\|false | Print stack trace for any errors encountered|
| `-J`, `--json` | `PORTAINER_BACKUP_JSON` | true\|false | Print formatted/strucutred JSON data |
| `-c`, `--concise` | `PORTAINER_BACKUP_CONCISE` | true\|false | Print concise/limited output |
| `-v`, `--version` | _(N/A)_ | | Show utility version number |
| `-h`, `--help` | _(N/A)_ | | Show help |

> **NOTE:** If both an environment variable and a command line option are configured for the same option, the command line option will take priority.

---

## Schedule Expression

**Portainer-backup** accepts a cron-like expression via the `--schedule` option or `PORTAINER_BACKUP_SCHEDULE` environment variable

> **NOTE:** Additional details on the supported cron syntax can be found here: https://github.com/node-cron/node-cron/blob/master/README.md#cron-syntax

```
Syntax Format:

┌──────────────────────── second (optional)
│ ┌──────────────────── minute
│ │ ┌──────────────── hour
│ │ │ ┌──────────── day of month
│ │ │ │ ┌──────── month
│ │ │ │ │ ┌──── day of week
│ │ │ │ │ │
│ │ │ │ │ │
* * * * * *

Examples:

0 0 0 * * * Daily at 12:00am
0 0 5 1 * * 1st day of month @ 5:00am
0 */15 0 * * * Every 15 minutes
```

### Allowed field values

| field | value |
|--------------|---------------------|
| second | 0-59 |
| minute | 0-59 |
| hour | 0-23 |
| day of month | 1-31 |
| month | 1-12 (or names) |
| day of week | 0-7 (or names, 0 or 7 are sunday) |

#### Using multiples values

| Expression | Description |
| ---------- | ----------- |
| `0 0 4,8,12 * * *` | Runs at 4p, 8p and 12p |

#### Using ranges

| Expression | Description |
| ---------- | ----------- |
| `0 0 1-5 * * *` | Runs hourly from 1 to 5 |

#### Using step values

Step values can be used in conjunction with ranges, following a range with '/' and a number. e.g: `1-10/2` that is the same as `2,4,6,8,10`. Steps are also permitted after an asterisk, so if you want to say “every two minutes”, just use `*/2`.

| Expression | Description |
| ---------- | ----------- |
| `0 0 */2 * * *` | Runs every 2 hours |

#### Using names

For month and week day you also may use names or short names. e.g:

| Expression | Description |
| ---------- | ----------- |
| `* * * * January,September Sunday` | Runs on Sundays of January and September |
| `* * * * Jan,Sep Sun` | Runs on Sundays of January and September |

---

## Filename & Directory Date/Time Substituions

**Portainer-backup** supports a substituion syntax for dynamically assigning date and time elements to the **directory** and **filename** options.

| Command Line Option | Environment Variable |
| ------------------- | -------------------- |
| `-d`, `--directory`, `--dir` | `PORTAINER_BACKUP_DIRECTORY` |
| `-f`, `--filename` | `PORTAINER_BACKUP_FILENAME` |

All substitution presets and/or tokens are included in between double curly braces: `{{ PRESET|TOKEN }}`

Example:
```
--filename "portainer-backup-{{DATE}}.tar.gz"
```

**Portainer-backup** uses the [Luxon](https://moment.github.io) library for parting date and time syntax. Please see https://moment.github.io/luxon/#/formatting for more information.

All date and times are rendered in the local date/time of the system running the **portainer-backup** utility. Alternatively you can incude the `UTC_` prefix in front of any of the tokens below to use UTC time instead.

Filenames are also processed through a `sanitize` funtion whick will strip characters that are not supported in filename. The `:` character is replaced with `_` and the `/` character is replaced with `-`.

### Supported Presets

The folllowing substition **presets** are defined by and supported in **portainer-backup**:

| Token | Format | Example (US) |
| ----- | ------ | ------------ |
| `DATETIME` | `yyyy-MM-dd'T'HHmmss` | 2022-03-05T231356 |
| `TIMESTAMP` | `yyyyMMdd'T'HHmmss.SSSZZZ` | 20220305T184827.445-0500 |
| `DATE` | `yyyy-MM-dd` | 2022-03-05 |
| `TIME` | `HHmmss` | 231356 |
| `ISO8601` | `yyyy-MM-dd'T'hh_mm_ss.SSSZZ` | 2017-04-20T11_32_00.000-04_00 |
| `ISO` | `yyyy-MM-dd'T'hh_mm_ss.SSSZZ` | 2017-04-20T11_32_00.000-04_00 |
| `ISO_BASIC` | `yyyyMMdd'T'hhmmss.SSSZZZ` | 20220305T191048.871-05_00 |
| `ISO_NO_OFFSET` | `yyyy-MM-dd'T'hh_mm_ss.SSS` | 2022-03-05T19_12_43.296 |
| `ISO_DATE` | `yyyy-MM-dd` | 2017-04-20 |
| `ISO_WEEKDATE` | `yyyy-'W'kk-c` | 2017-W17-7 |
| `ISO_TIME` | `hh_mm_ss.SSSZZZ` | 11_32_00.000-04_00 |
| `RFC2822` | `ccc, dd LLL yyyy HH_mm_ss ZZZ` | Thu, 20 Apr 2017 11_32_00 -0400 |
| `HTTP` | `ccc, dd LLL yyyy HH_mm_ss ZZZZ` | Thu, 20 Apr 2017 03_32_00 GMT |
| `MILLIS` | `x` | 1492702320000 |
| `SECONDS` | `X` | 1492702320.000 |
| `UNIX` | `X` | 1492702320.000 |
| `EPOCH` | `X` | 1492702320.000 |

The folllowing substition **presets** are provided my the [Luxon](https://moment.github.io) library and are supported in **portainer-backup**:
(See the following Luxon docs for more information: https://moment.github.io/luxon/#/formatting?id=presets)

(The following presets are using the October 14, 1983 at `13:30:23` as an example.)

| Name | Description | Example in en_US | Example in fr |
| ---------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------ | ---------------------------------------------------------- |
| `DATE_SHORT` | short date | `10/14/1983` | `14/10/1983` |
| `DATE_MED` | abbreviated date | `Oct 14, 1983` | `14 oct. 1983` |
| `DATE_MED_WITH_WEEKDAY` | abbreviated date with abbreviated weekday | `Fri, Oct 14, 1983` | `ven. 14 oct. 1983` |
| `DATE_FULL` | full date | `October 14, 1983` | `14 octobre 1983` |
| `DATE_HUGE` | full date with weekday | `Friday, October 14, 1983` | `vendredi 14 octobre 1983` |
| `TIME_SIMPLE` | time | `1:30 PM` | `13:30` |
| `TIME_WITH_SECONDS` | time with seconds | `1:30:23 PM` | `13:30:23` |
| `TIME_WITH_SHORT_OFFSET` | time with seconds and abbreviated named offset | `1:30:23 PM EDT` | `13:30:23 UTC−4` |
| `TIME_WITH_LONG_OFFSET` | time with seconds and full named offset | `1:30:23 PM Eastern Daylight Time` | `13:30:23 heure d’été de l’Est` |
| `TIME_24_SIMPLE` | 24-hour time | `13:30` | `13:30` |
| `TIME_24_WITH_SECONDS` | 24-hour time with seconds | `13:30:23` | `13:30:23` |
| `TIME_24_WITH_SHORT_OFFSET` | 24-hour time with seconds and abbreviated named offset | `13:30:23 EDT` | `13:30:23 UTC−4` |
| `TIME_24_WITH_LONG_OFFSET` | 24-hour time with seconds and full named offset | `13:30:23 Eastern Daylight Time` | `13:30:23 heure d’été de l’Est` |
| `DATETIME_SHORT` | short date & time | `10/14/1983, 1:30 PM` | `14/10/1983 à 13:30` |
| `DATETIME_MED` | abbreviated date & time | `Oct 14, 1983, 1:30 PM` | `14 oct. 1983 à 13:30` |
| `DATETIME_FULL` | full date and time with abbreviated named offset | `October 14, 1983, 1:30 PM EDT` | `14 octobre 1983 à 13:30 UTC−4` |
| `DATETIME_HUGE` | full date and time with weekday and full named offset | `Friday, October 14, 1983, 1:30 PM Eastern Daylight Time` | `vendredi 14 octobre 1983 à 13:30 heure d’été de l’Est` |
| `DATETIME_SHORT_WITH_SECONDS`| short date & time with seconds | `10/14/1983, 1:30:23 PM` | `14/10/1983 à 13:30:23` |
| `DATETIME_MED_WITH_SECONDS` | abbreviated date & time with seconds | `Oct 14, 1983, 1:30:23 PM` | `14 oct. 1983 à 13:30:23` |
| `DATETIME_FULL_WITH_SECONDS` | full date and time with abbreviated named offset with seconds | `October 14, 1983, 1:30:23 PM EDT` | `14 octobre 1983 à 13:30:23 UTC−4` |
| `DATETIME_HUGE_WITH_SECONDS` | full date and time with weekday and full named offset with seconds | `Friday, October 14, 1983, 1:30:23 PM Eastern Daylight Time` | `vendredi 14 octobre 1983 à 13:30:23 heure d’été de l’Est` |

### Supported Tokens

If one of the substitution presets does not meet your needs, you can build your own date/time string using the supported **tokens** listed below.
(See the following Luxon docs for more information: https://moment.github.io/luxon/#/formatting?id=table-of-tokens)

Example:

```
--filename "portainer-backup-{{yyyy-MM-dd}}.tar.gz"
```

(Examples below given for `2014-08-06T13:07:04.054` considered as a local time in America/New_York.)

| Standalone token | Format token | Description | Example |
| ---------------- | ------------ | -------------------------------------------------------------- | ------------------------------------------------------------- |
| S | | millisecond, no padding | `54` |
| SSS | | millisecond, padded to 3 | `054` |
| u | | fractional seconds, functionally identical to SSS | `054` |
| uu | | fractional seconds, between 0 and 99, padded to 2 | `05` |
| uuu | | fractional seconds, between 0 and 9 | `0` |
| s | | second, no padding | `4` |
| ss | | second, padded to 2 padding | `04` |
| m | | minute, no padding | `7` |
| mm | | minute, padded to 2 | `07` |
| h | | hour in 12-hour time, no padding | `1` |
| hh | | hour in 12-hour time, padded to 2 | `01` |
| H | | hour in 24-hour time, no padding | `9` |
| HH | | hour in 24-hour time, padded to 2 | `13` |
| Z | | narrow offset | `+5` |
| ZZ | | short offset | `+05:00` |
| ZZZ | | techie offset | `+0500` |
| ZZZZ | | abbreviated named offset | `EST` |
| ZZZZZ | | unabbreviated named offset | `Eastern Standard Time` |
| z | | IANA zone | `America/New_York` |
| a | | meridiem | `AM` |
| d | | day of the month, no padding | `6` |
| dd | | day of the month, padded to 2 | `06` |
| c | E | day of the week, as number from 1-7 (Monday is 1, Sunday is 7) | `3` |
| ccc | EEE | day of the week, as an abbreviate localized string | `Wed` |
| cccc | EEEE | day of the week, as an unabbreviated localized string | `Wednesday` |
| ccccc | EEEEE | day of the week, as a single localized letter | `W` |
| L | M | month as an unpadded number | `8` |
| LL | MM | month as a padded number | `08` |
| LLL | MMM | month as an abbreviated localized string | `Aug` |
| LLLL | MMMM | month as an unabbreviated localized string | `August` |
| LLLLL | MMMMM | month as a single localized letter | `A` |
| y | | year, unpadded | `2014` |
| yy | | two-digit year | `14` |
| yyyy | | four- to six- digit year, pads to 4 | `2014` |
| G | | abbreviated localized era | `AD` |
| GG | | unabbreviated localized era | `Anno Domini` |
| GGGGG | | one-letter localized era | `A` |
| kk | | ISO week year, unpadded | `14` |
| kkkk | | ISO week year, padded to 4 | `2014` |
| W | | ISO week number, unpadded | `32` |
| WW | | ISO week number, padded to 2 | `32` |
| o | | ordinal (day of year), unpadded | `218` |
| ooo | | ordinal (day of year), padded to 3 | `218` |
| q | | quarter, no padding | `3` |
| qq | | quarter, padded to 2 | `03` |
| D | | localized numeric date | `9/4/2017` |
| DD | | localized date with abbreviated month | `Aug 6, 2014` |
| DDD | | localized date with full month | `August 6, 2014` |
| DDDD | | localized date with full month and weekday | `Wednesday, August 6, 2014` |
| t | | localized time | `9:07 AM` |
| tt | | localized time with seconds | `1:07:04 PM` |
| ttt | | localized time with seconds and abbreviated offset | `1:07:04 PM EDT` |
| tttt | | localized time with seconds and full offset | `1:07:04 PM Eastern Daylight Time` |
| T | | localized 24-hour time | `13:07` |
| TT | | localized 24-hour time with seconds | `13:07:04` |
| TTT | | localized 24-hour time with seconds and abbreviated offset | `13:07:04 EDT` |
| TTTT | | localized 24-hour time with seconds and full offset | `13:07:04 Eastern Daylight Time` |
| f | | short localized date and time | `8/6/2014, 1:07 PM` |
| ff | | less short localized date and time | `Aug 6, 2014, 1:07 PM` |
| fff | | verbose localized date and time | `August 6, 2014, 1:07 PM EDT` |
| ffff | | extra verbose localized date and time | `Wednesday, August 6, 2014, 1:07 PM Eastern Daylight Time` |
| F | | short localized date and time with seconds | `8/6/2014, 1:07:04 PM` |
| FF | | less short localized date and time with seconds | `Aug 6, 2014, 1:07:04 PM` |
| FFF | | verbose localized date and time with seconds | `August 6, 2014, 1:07:04 PM EDT` |
| FFFF | | extra verbose localized date and time with seconds | `Wednesday, August 6, 2014, 1:07:04 PM Eastern Daylight Time` |
| X | | unix timestamp in seconds | `1407287224` |
| x | | unix timestamp in milliseconds | `1407287224054` |

---

## Command Line Help

Use the `help` command or `--help` option to see a listing of command line options directly via the CLI.

```
___ _ _ ___ _
| _ \___ _ _| |_ __ _(_)_ _ ___ _ _ | _ ) __ _ __| |___ _ _ __
| _/ _ \ '_| _/ _` | | ' \/ -_) '_| | _ \/ _` / _| / / || | '_ \
|_| \___/_| \__\__,_|_|_||_\___|_| |___/\__,_\__|_\_\\_,_| .__/
|_|
┌──────────────────────────────────────────────────────────────────┐
│ Made with ♥ by SavageSoftware, LLC © 2022 (Version 0.0.6) │
└──────────────────────────────────────────────────────────────────┘

Usage: [(options...)]

Commands:
portainer-backup backup Backup portainer data
portainer-backup schedule Run scheduled portainer backups
portainer-backup stacks Backup portainer stacks
portainer-backup info Get portainer server info
portainer-backup test Test backup data & stacks (backup --dryru
n --stacks)
portainer-backup restore Restore portainer data
portainer-backup help Show help
portainer-backup version Show version

Portainer Options:
-t, --token Portainer access token
[string] [default: ""]
-u, --url Portainer base url
[string] [default: "http://portainer:9000"]
-Z, --ignore-version Bypass portainer version check/enforcement
[boolean] [default: false]

Backup Options: (applies only to 'backup' command)
-d, --directory, --dir Backup directory/path
[string] [default: "/backup"]
-f, --filename Backup filename
[string] [default: "portainer-backup.tar.gz"]
-p, --password, --pwd Backup archive password [string] [default: ""]
-o, --overwrite Overwrite existing files
[boolean] [default: false]
-M, --mkdir, --make-directory Create backup directory path if needed
[boolean] [default: false]
-s, --schedule, --sch Cron expression for scheduled backups
[string] [default: "0 0 0 * * * *"]
-i, --include-stacks, --stacks Include stack files in backup
[boolean] [default: false]

Stacks Options: (applies only to 'stacks' command)
-d, --directory, --dir Backup directory/path [string] [default: "/backup"]
-o, --overwrite Overwrite existing files [boolean] [default: false]
-M, --mkdir, --make-directory Create backup directory path if needed
[boolean] [default: false]
Restore Options: (applies only to 'restore' command)
-p, --password, --pwd Backup archive password [string] [default: ""]

Options:
-h, --help Show help [boolean]
-q, --quiet Do not display any console output [boolean] [default: false]
-D, --dryrun Execute command task without persisting any data.
[boolean] [default: false]
-X, --debug Print details stack trace for any errors encountered
[boolean] [default: false]
-J, --json Print formatted/strucutred JSON data [boolean] [default: false]
-c, --concise Print concise/limited output [boolean] [default: false]
-v, --version Show version number [boolean]

Command Examples:
info --url http://192.168.1.100:9000

backup --url http://192.168.1.100:9000
--token XXXXXXXXXXXXXXXX
--overwrite
--stacks

stacks --url http://192.168.1.100:9000
--token XXXXXXXXXXXXXXXX
--overwrite

restore --url http://192.168.1.100:9000
--token XXXXXXXXXXXXXXXX
./file-to-restore.tar.gz

schedule --url http://192.168.1.100:9000
--token XXXXXXXXXXXXXXXX
--schedule "0 0 0 * * *"

Schedule Expression Examples: (cron syntax)

┌──────────────────────── second (optional)
│ ┌──────────────────── minute
│ │ ┌──────────────── hour
│ │ │ ┌──────────── day of month
│ │ │ │ ┌──────── month
│ │ │ │ │ ┌──── day of week
│ │ │ │ │ │
│ │ │ │ │ │
* * * * * *

0 0 0 * * * Daily at 12:00am
0 0 5 1 * * 1st day of month @ 5:00am
0 */15 0 * * * Every 15 minutes

Additional Examples @ https://github.com/node-cron/node-cron#cron-syntax
```

---

## Docker Compose

Alternatively you can use a `docker-compose.yml` file to launch your **portainer-backup** container. Below is a sample `docker-compose.yml` file you can use to get started:

```yaml
version: '3.8'
services:
portainer-backup:
container_name: portainer-backup
image: savagesoftware/portainer-backup:latest
hostname: portainer-backup
restart: unless-stopped
command: schedule
environment:
TZ: America/New_York
PORTAINER_BACKUP_URL: "http://portainer:9000"
PORTAINER_BACKUP_TOKEN: "PORTAINER_ACCESS_TOKEN"
PORTAINER_BACKUP_PASSWORD: ""
PORTAINER_BACKUP_OVERWRITE: 1
PORTAINER_BACKUP_SCHEDULE: "0 0 0 * * *"
PORTAINER_BACKUP_STACKS: 1
PORTAINER_BACKUP_DRYRUN: 0
PORTAINER_BACKUP_CONCISE: 1
PORTAINER_BACKUP_DIRECTORY: "/backup"
PORTAINER_BACKUP_FILENAME: "portainer-backup.tar.gz"
volumes:
- /var/backup:/backup
```

Just run the `docker-compose up -d` command in the same directory as your `docker-compose.yml` file to launch the container instance.

Supported Docker platforms:
* `linux/amd64` (Intel/AMD x64)
* `linux/arm64` (ARMv8)
* `linux/arm` (ARMv7)

---