Attributes
Includes Deno configuration
Repository
Current version released
2 months ago
Dependencies
DFtpS - Deno Ftp Server
DFtpS is an FTP server based on ftp-srv with Deno.
Version 2.0.0 - Fully modernized for Deno 2.x with:
- JSR-based imports (
@std/*,@cliffy/*) - Drizzle ORM (replacing deprecated denodb)
- Argon2 password hashing (replacing scrypt)
- Native Streams API (no more BufReader/BufWriter)
- Full TypeScript strict mode
Check our guide in https://mnlaugh.github.io/dftps-guide/guide/
Usage
Install
curl -fsSL https://deno.land/x/dftps/install.sh | shInstall Specific Version
curl -fsSL https://deno.land/x/dftps/install.sh | sh -s v1.0.0Make your own
Simple
- First, we import the Server class and type for user authentication.
import { Server } from "jsr:@dftps/server";
import type { LoginResolvable, UsernameResolvable } from "jsr:@dftps/server";- Then we just need to create an instance of Server with these options described below.
const serve = new Server({ port: 21, hostname: "127.0.0.1" });- All we have to do is wait for a new connection and check the veracity of it using the authentication tools (awaitUsername, awaitLogin).
for await (const connection of serve) {
const { awaitUsername, awaitLogin } = connection;
/** waiting to receiving username from connection */
awaitUsername.then(({ username, resolveUsername }: UsernameResolvable) => {
if (username !== "my-username") return resolveUsername.reject("Incorrect username!");
resolveUsername.resolve();
});
/** waiting to receiving password from connection and finalize the user authenticate */
awaitLogin.then(({ password, resolvePassword }: LoginResolvable) => {
if (password !== "my-password") return resolvePassword.reject("Wrong password!");
resolvePassword.resolve({ root: "my-folder", uid: 1000, gid: 1000 });
});
}With database
Import the database utilities:
import { createDb, Server } from "jsr:@dftps/server"; import { verify } from "@node-rs/argon2";
Database configuration (SQLite):
- SQLite Options
- filepath [string] (Required) - Path to the SQLite database file
- SQLite Options
/** Initialize SQLite database and pass it to the server */
const db = createDb({ connector: "SQLite", filepath: "./data/dftps.db" });
const serve = new Server(
{ port: 21, hostname: "127.0.0.1" },
{ database: db }, // Inject database into server
);
for await (const connection of serve) {
const { awaitUsername, awaitLogin } = connection;
let user: User | undefined;
/** Waiting to receiving username from connection */
awaitUsername.then(async ({ username, resolveUsername }: UsernameResolvable) => {
/** Find user via server.users */
user = serve.users?.findByUsername(username);
if (!user) return resolveUsername.reject("Incorrect username!");
resolveUsername.resolve();
});
/** Waiting to receiving password from connection and finalize the user authenticate */
awaitLogin.then(async ({ password, resolvePassword }: LoginResolvable) => {
if (!user) return resolvePassword.reject("User not found!");
if (!await verify(user.password, password)) return resolvePassword.reject("Wrong password!");
const { root, uid, gid } = user;
resolvePassword.resolve({ root, uid, gid });
});
}Note: You can also use the static
Usersclass directly (legacy approach), but injecting the database via{ database: db }is recommended for multi-instance scenarios.
## Log example

---
## Deno Dependencies
All dependencies are now available via [JSR](https://jsr.io) with modern Deno 2.x compatibility:
- ### Standard Library (JSR)
- [@std/async](https://jsr.io/@std/async) - Async utilities
- [@std/path](https://jsr.io/@std/path) - Path manipulation
- [@std/fs](https://jsr.io/@std/fs) - File system operations
- [@std/datetime](https://jsr.io/@std/datetime) - Date/time formatting
- [@std/assert](https://jsr.io/@std/assert) - Assertions
- ### CLI Framework
- [@cliffy/command](https://jsr.io/@cliffy/command) - CLI commands
- [@cliffy/table](https://jsr.io/@cliffy/table) - Table formatting
- [@cliffy/ansi](https://jsr.io/@cliffy/ansi) - ANSI colors
- ### Database
- [@db/sqlite](https://jsr.io/@db/sqlite) - Native SQLite for Deno
- ### Security
- [@node-rs/argon2](https://www.npmjs.com/package/@node-rs/argon2) - Password hashing
## [List of FTP commands](https://en.wikipedia.org/wiki/List_of_FTP_commands)
See [COMMANDS.md](COMMANDS.md)
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
## References
- [Ftp](https://cr.yp.to/ftp.html)
- [Ftp commands](https://en.wikipedia.org/wiki/List_of_FTP_commands)
- [Ftp reply codes](https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes)