ftpgrab pulls files off FTP and SFTP servers on a schedule, skipping what it already has
Grab your files periodically from a remote FTP or SFTP server easily
At a glance
- What is it?
- ftpgrab is a Go command-line tool for unattended transfers, built for seedboxes and home servers, that filters what to download, avoids re-fetching files it already grabbed, sends notifications after runs, and ships as a single executable or a container image. It suits anyone automating a recurring pull from a remote box, and its assumption that the remote side is stable and the local side is a NAS is narrower than the name suggests.
- Who is it for?
- Seedbox users, home server operators and NAS owners who need a recurring pull from a remote box into local storage are the people ftpgrab is for, and the fact that it ships as both a single executable and a container image means it fits either a cron entry or a compose stack. It is the wrong tool for a one-off download, where a plain FTP client does the same job with less to configure, and it is the wrong tool if you need two-way sync, since the model is explicitly a pull.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 60 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A pull tool for unattended transfers, not a sync client
The project describes itself as a command-line tool for pulling files from remote FTP and SFTP servers to your NAS, server, or computer, and it is built for unattended transfers. That word, unattended, is the design brief. You point it at one or more remote sources, run it on a schedule, filter what should be downloaded, and avoid re-downloading files that were already grabbed. The audience is stated plainly in the readme: it works well for seedboxes, home servers, and any setup where files need to move reliably from a remote server to local storage. The topics attached to the repository reinforce the same picture, naming seedbox, nas, qnap, synology, ftp, sftp, scheduler and download. So this is the tool you reach for when a torrent client finishes something on a remote box and the file has to end up on the NAS at home, on a schedule, without you watching.
Scheduling is a cron expression, not a daemon
The schedule is handled by a cron library rather than by a long-running process, and the dependency list names it directly, robfig/cron v3. That choice has a practical consequence. A cron-driven tool is invoked, does a pass, and exits, so the thing that keeps it running is the system scheduler or the container orchestrator, and that means the state about what has already been downloaded has to live somewhere durable rather than in memory. The other half of the design is the notification, because the readme says the tool can send notifications after runs so you can keep track of successful downloads, failures and other activity without babysitting the job. Put together, the model is: a scheduler triggers a run, the run compares remote state against local state, and the result is reported. That is a different shape from a daemon that holds a connection open, and it is the shape that survives a reboot of the machine running the NAS.
State about previous grabs is kept in a BoltDB file
The skip logic needs somewhere to record what has already been fetched, and the dependency list points at where that lives, go.etcd.io/bbolt v1.4.3, the embedded BoltDB key-value store. A local file database is the right fit for this job, because the tool runs as a scheduled process, and the state it needs is a set of records rather than a queryable relational dataset. The alternative design, where the tool asks the remote server what is new, works too but puts the burden on the server's listing semantics, which differ between FTP and SFTP and between server implementations. Keeping a local record also means the tool can be pointed at a server that does not support modification times reliably. The repository layout shows a conventional Go project with cmd, internal, test and hack directories, a vendored dependency tree, a docs directory with a mkdocs configuration, a Dockerfile and a docker-bake.hcl for the image build, and a changelog. The Go module is majored at version seven, github.com/crazy-max/ftpgrab/v7, and it requires Go 1.26.0.
FTP and SFTP are separate libraries behind one interface
The two protocols are handled by distinct dependencies, github.com/pkg/sftp v1.13.10 for SFTP and github.com/jlaffaye/ftp v0.2.0 for FTP, and the presence of golang.org/x/crypto in the list is the SSH layer underneath the SFTP client. Handling both behind a common interface is the point, because a home setup often has one box speaking SFTP with an SSH key and another speaking plain FTP, and the readme's phrasing of one or more remote sources implies that a single run can cover both kinds. The other libraries in the list tell you what else the tool does. The hako/durafmt package formats durations in human terms, which is what you want in a run summary. The rotatewriter package rotates log files. The gonfig package is a configuration loader, and the alecthomas/kong library is the command line parser. The nlopes/slack library is the Slack notification channel, and go-gomail is the mail one.
Notifications go out by mail or Slack after the run
The two notification integrations are visible in the dependency list rather than in the feature list, and it is worth knowing before you configure the tool. go-gomail/gomail handles email and nlopes/slack handles Slack, which means a run can report successful downloads, failures and other activity through either channel. Neither is a generic webhook, so if your team runs a different alerting system, the extension point is not obvious from what the documentation says. There is also hermes, matcornic/hermes, which is a message templating library, which suggests the notification bodies are template-driven rather than hard-coded strings. The readme's tip section points at a sibling project, Diun, for being notified about new releases of container images, which is a different job but tells you the maintainer builds tooling around the Docker image update problem.
Two distribution shapes, one static binary and a scratch-based image
FTPGrab is available as a single executable and as a container image, and the Dockerfile shows the second one being built with some care. The build uses xx for cross-compilation, with Go 1.26 on Alpine 3.23 as the base, CGO disabled, and GOFLAGS set to vendor mode so the build uses the checked-in vendor tree. The binary stage compiles the cmd directory with a trimmed path and a version stamped in from the git ref, then runs xx-verify to check the result is static. The final images are built from scratch, with separate stages for the Unix, Windows, Darwin and FreeBSD binaries, and the test stage runs the suite with the race detector and a coverage profile. The Makefile in the repository has a vendor target that runs docker buildx bake to produce the vendored dependencies, so the release artefact is reproducible from the committed tree rather than resolved at build time.
ENV CGO_ENABLED=0
ENV GOFLAGS="-mod=vendor"Where ftpgrab is the wrong choice
The first wrong case is a one-off download, where the readme's own framing of unattended scheduled transfers is more machinery than the job needs, and any FTP or SFTP client will do. The second is a workflow that needs two-way movement, since the tool is a pull and nothing in the description suggests it pushes local changes back. The third is a target that does not speak FTP or SFTP, since the whole implementation is those two protocols and there is no indication of a web or object store backend. The fourth is an environment where the remote server cannot be listed reliably, because the filters and the skip logic both depend on the remote directory listing being consistent, and the documentation does not describe what happens when a listing is partial. The fifth is a team that wants the grab history in a database it can query, because the state lives in an embedded key-value file that only the tool reads. The sixth is a fresh install where the notification and schedule configuration is the first thing you must get right, because a run that fails silently on a NAS is worse than no run at all.
Editorial conclusion
Seedbox users, home server operators and NAS owners who need a recurring pull from a remote box into local storage are the people ftpgrab is for, and the fact that it ships as both a single executable and a container image means it fits either a cron entry or a compose stack. It is the wrong tool for a one-off download, where a plain FTP client does the same job with less to configure, and it is the wrong tool if you need two-way sync, since the model is explicitly a pull. Check three things before you deploy it: which notification channel you want, since the dependency list shows mail and Slack integrations and nothing else, that your remote server exposes what the client expects over FTP or SFTP, and whether your local destination is on a filesystem the tool can track state against, since the point of the skip logic is remembering what has already been grabbed. The licence is MIT, the newest release is v7.13.0 from 2026-04-17, and the last push was on 2026-08-24.
Frequently asked questions
What does ftpgrab do and who is it for?
It is a command-line tool for pulling files from remote FTP and SFTP servers to your NAS, server or computer, built for unattended scheduled transfers. The readme says it works well for seedboxes, home servers and any setup where files need to move reliably from a remote server to local storage.
How does ftpgrab avoid downloading the same file twice?
It keeps state about what it has already grabbed in an embedded key-value store, go.etcd.io/bbolt, so a scheduled run can skip files that were already fetched. The readme describes this as avoiding re-downloading files that were already grabbed.
How is ftpgrab scheduled and how does it report results?
Scheduling uses a cron expression through the robfig/cron library, and the tool can send notifications after runs so you can track successful downloads and failures without watching the job. The dependency list shows email through go-gomail and Slack through nlopes/slack as the notification channels.
How do I install ftpgrab?
It is available as a single executable from the GitHub releases, or as a container image on Docker Hub under crazymax/ftpgrab. The image is built from scratch with a static binary produced by xx-go build and checked with xx-verify, and the project also publishes documentation built with mkdocs.
Which protocols does ftpgrab support?
FTP and SFTP, handled by separate client libraries, github.com/jlaffaye/ftp and github.com/pkg/sftp with golang.org/x/crypto underneath for the SSH layer. The readme describes pointing it at one or more remote sources in a single run.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/crazy-max-ftpgrab)Was this useful?