Sign inSign up

usernahme/ftp-backup

By usernahme

•Updated about 16 hours ago

FTP/FTPS pull backup that keeps the last N versions. Rebuilt weekly with current packages.

Image
0

151

usernahme/ftp-backup repository overview

⁠ftp-backup

A small Alpine-based container that pulls a directory via FTP/FTPS – for example the web space of a shared hosting account – on a schedule and keeps the last N versions.

Retention is by count, not age: with KEEP=5 you always have the five most recent backups, no matter how long ago they ran. Old versions are only deleted after a new backup has succeeded.

Multi-arch: linux/amd64, linux/arm64, linux/arm/v7 (Raspberry Pi). (Depending on how the image was built – check the tag's OS/ARCH list.)

⁠Always up to date – rebuilt every week

This image is rebuilt from scratch every week – on the current Alpine base image and without build cache. Every build pulls the latest versions of all included packages (lftp, curl, OpenSSL, CA certificates, BusyBox …), so security fixes land in the image automatically within a week, without you having to do anything.

To benefit from it, simply pull latest regularly (e.g. with Watchtower or docker compose pull && docker compose up -d).

⁠Tags

TagMeaning
latestMost recent weekly build – recommended
YYYY-MM-DDBuild of that day – pin this if you need a fixed version or want to roll back

Only the six most recent dated builds are kept; older tags are removed automatically.

⁠Features

  • Incremental mirror with lftp – only changed files are transferred, files deleted on the server are removed locally
  • Dated tar.gz version per run, rotated to KEEP versions
  • FTPS (TLS) enforced by default, certificate verification on
  • Built-in cron scheduler, logs go to docker logs
  • E-mail notification on failure (or always) via any SMTP server – with or without auth, plain/STARTTLS/SSL
  • Passwords from files (Docker secrets) instead of environment variables
  • Healthcheck: container turns unhealthy if the last run failed or the last successful backup is too old
  • Rebuilt weekly with current packages – see below

⁠Quick start (docker compose)

services:
  website-backup:
    image: usernahme/ftp-backup:latest
    container_name: website-backup
    restart: unless-stopped
    environment:
      TZ: Europe/Berlin
      CRON_SCHEDULE: "15 3 * * *"
      KEEP: "5"
      PREFIX: "website"
      FTP_HOST: "ftp.example.com"
      FTP_USER: "username"
      FTP_PASS_FILE: /run/secrets/ftp_pass
      REMOTE_DIR: "/"
      EXCLUDES: "logs/ cache/"
      MAIL_TO: "[email protected]"
      SMTP_HOST: "mail.example.com"
    secrets:
      - ftp_pass
    volumes:
      - /srv/backup/website:/data

secrets:
  ftp_pass:
    file: ./ftp_pass.txt
docker compose up -d
docker exec website-backup backup.sh      # run a backup now
docker logs -f website-backup

One-shot run without cron:

docker run --rm -e FTP_HOST=... -e FTP_USER=... -e FTP_PASS=... \
  -v /srv/backup/website:/data DEIN_DOCKERHUB_NAME/ftp-backup run

⁠Volume layout

/data
├── mirror/                           # current incremental mirror
├── versions/
│   ├── website-20261101-031500.tar.gz
│   └── ...                           # last KEEP versions
└── .last_status                      # used by the healthcheck

⁠Environment variables

⁠Backup
VariableDefaultDescription
FTP_HOST–Server, optionally host:port
FTP_USER–Username
FTP_PASS / FTP_PASS_FILE–Password, or path to a file containing it
REMOTE_DIR/Source directory on the server
KEEP5Number of versions to keep
PREFIXbackupFile name prefix
CRON_SCHEDULE15 3 * * *Schedule (cron syntax)
TZEurope/BerlinTime zone
EXCLUDES–Space-separated globs, e.g. logs/ cache/
USE_FTPSyesEnforce TLS
VERIFY_CERTyesVerify the server certificate
PARALLEL4Parallel downloads
RUN_ON_STARTnoRun a backup when the container starts
MAX_AGE_HOURS26Healthcheck: unhealthy if the last success is older
⁠E-mail notification
VariableDefaultDescription
NOTIFYerrorerror, always or never
MAIL_TO–Recipient(s), comma-separated – no mail if empty
MAIL_FROMftp-backup@<hostname>Sender address
SMTP_HOST–SMTP server – no mail if empty
SMTP_PORT25Port (587 for STARTTLS, 465 for SSL)
SMTP_TLSnonenone, starttls or ssl
SMTP_USER–Username, empty = no authentication
SMTP_PASS / SMTP_PASS_FILE–Password, or path to a file containing it
SMTP_VERIFY_CERTyesVerify the SMTP server certificate

The mail contains the full log of the run.

⁠Restore

mkdir /tmp/restore
tar -xzf /srv/backup/website/versions/website-....tar.gz -C /tmp/restore
# then upload back, e.g.:  lftp -u user ftp.example.com -e "mirror -R /tmp/restore /; quit"

⁠Limitations

Only files are backed up. Databases on the hosting account (e.g. MySQL) are not included.

Tag summary

Content type

Image

Digest

sha256:813906f57…

Size

10.2 MB

Last updated

about 16 hours ago

docker pull usernahme/ftp-backup