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 and the Users repository:
import { Server, verify } from "jsr:@dftps/server"; import { createDb, type User, Users } from "jsr:@dftps/server/db";
Database configuration (SQLite):
- SQLite Options
- filepath [string] (Required) - Path to the SQLite database file
- SQLite Options
/** Initialize SQLite database */
const db = createDb({ connector: "SQLite", filepath: "./data/dftps.db" });
const serve = new Server(ListenOptions, FTPServerOptions);
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 in database */
user = await 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 });
});
}Log example

Deno Dependencies
All dependencies are now available via JSR with modern Deno 2.x compatibility:
Standard Library (JSR)
- @std/async - Async utilities
- @std/path - Path manipulation
- @std/fs - File system operations
- @std/datetime - Date/time formatting
- @std/assert - Assertions
CLI Framework
- @cliffy/command - CLI commands
- @cliffy/table - Table formatting
- @cliffy/ansi - ANSI colors
Database
- @db/sqlite - Native SQLite for Deno
Security
- @node-rs/argon2 - Password hashing
List of FTP commands
See COMMANDS.md
Contributing
See CONTRIBUTING.md